From f03b8582eb678c543cec6706b8f0e8a2c62dd3a8 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 20 Jun 2019 16:41:30 -0400 Subject: [PATCH 001/337] Initial Commit. --- .../monitoring/blackbox/ActionHandler.java | 5 + .../monitoring/blackbox/ProbingAction.java | 5 + .../monitoring/blackbox/ProbingSequence.java | 5 + .../monitoring/blackbox/ProbingStep.java | 5 + .../monitoring/blackbox/Protocol.java | 5 + .../monitoring/blackbox/TestToken.java | 5 + .../registry/monitoring/blackbox/Token.java | 5 + prober/build.gradle | 30 +- .../blackbox/AutoValue_NewChannelAction.java | 181 +++++++++++ .../blackbox/AutoValue_ProbingAction.java | 118 +++++++ .../blackbox/AutoValue_Protocol.java | 153 +++++++++ .../monitoring/blackbox/ActionHandler.java | 52 +++ .../registry/monitoring/blackbox/Main.java | 8 + .../monitoring/blackbox/NewChannelAction.java | 70 +++++ .../monitoring/blackbox/ProbingAction.java | 295 ++++-------------- .../monitoring/blackbox/ProbingFlows.java | 15 + .../monitoring/blackbox/ProbingSequence.java | 92 +----- .../monitoring/blackbox/ProbingStep.java | 207 +++--------- .../monitoring/blackbox/Protocol.java | 65 ++-- .../monitoring/blackbox/TestToken.java | 28 ++ .../registry/monitoring/blackbox/Token.java | 20 ++ .../monitoring/blackbox/package-info.java | 16 + 22 files changed, 841 insertions(+), 544 deletions(-) create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Main.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/package-info.java diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java new file mode 100644 index 00000000000..a4d36657721 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ActionHandler { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java new file mode 100644 index 00000000000..6b26913d425 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingAction { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java new file mode 100644 index 00000000000..9f3617135a4 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingSequence { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java new file mode 100644 index 00000000000..b8b237a1e91 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingStep { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java new file mode 100644 index 00000000000..75d13b3039a --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class Protocol { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java new file mode 100644 index 00000000000..98f21f8d63a --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class TestToken { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java new file mode 100644 index 00000000000..16f05be0430 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class Token { + +} diff --git a/prober/build.gradle b/prober/build.gradle index 3652390d0ba..33feefb7175 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,30 +1,25 @@ -// Copyright 2019 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. - apply plugin: 'java' -createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') +createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Main') + dependencies { def deps = rootProject.dependencyMap + compile deps['com.beust:jcommander'] + compile deps['com.google.api-client:google-api-client'] + compile deps['com.google.apis:google-api-services-cloudkms'] + compile deps['com.google.apis:google-api-services-monitoring'] + compile deps['com.google.apis:google-api-services-storage'] compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] + compile deps['com.google.http-client:google-http-client'] + compile deps['com.google.monitoring-client:metrics'] + compile deps['com.google.monitoring-client:stackdriver'] compile deps['io.netty:netty-buffer'] compile deps['io.netty:netty-codec-http'] compile deps['io.netty:netty-codec'] @@ -41,10 +36,13 @@ dependencies { runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] + testCompile deps['com.google.monitoring-client:contrib'] testCompile deps['com.google.truth:truth'] + testCompile deps['org.yaml:snakeyaml'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') + testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -52,4 +50,4 @@ dependencies { testAnnotationProcessor deps['com.google.auto.value:auto-value'] annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] -} +} \ No newline at end of file diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java new file mode 100644 index 00000000000..6f818f03a28 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java @@ -0,0 +1,181 @@ + + +package google.registry.monitoring.blackbox; + +import io.netty.bootstrap.Bootstrap; +import javax.annotation.Generated; +import org.joda.time.Duration; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_NewChannelAction extends NewChannelAction { + + private final Duration delay; + + private final O outboundMessage; + + private final Protocol protocol; + + private final ActionHandler actionHandler; + + private final Bootstrap bootstrap; + + private AutoValue_NewChannelAction( + Duration delay, + O outboundMessage, + Protocol protocol, + ActionHandler actionHandler, + Bootstrap bootstrap) { + this.delay = delay; + this.outboundMessage = outboundMessage; + this.protocol = protocol; + this.actionHandler = actionHandler; + this.bootstrap = bootstrap; + } + + @Override + Duration delay() { + return delay; + } + + @Override + O outboundMessage() { + return outboundMessage; + } + + @Override + Protocol protocol() { + return protocol; + } + + @Override + ActionHandler actionHandler() { + return actionHandler; + } + + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + @Override + public String toString() { + return "NewChannelAction{" + + "delay=" + delay + ", " + + "outboundMessage=" + outboundMessage + ", " + + "protocol=" + protocol + ", " + + "actionHandler=" + actionHandler + ", " + + "bootstrap=" + bootstrap + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof NewChannelAction) { + NewChannelAction that = (NewChannelAction) o; + return this.delay.equals(that.delay()) + && this.outboundMessage.equals(that.outboundMessage()) + && this.protocol.equals(that.protocol()) + && this.actionHandler.equals(that.actionHandler()) + && this.bootstrap.equals(that.bootstrap()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= delay.hashCode(); + h$ *= 1000003; + h$ ^= outboundMessage.hashCode(); + h$ *= 1000003; + h$ ^= protocol.hashCode(); + h$ *= 1000003; + h$ ^= actionHandler.hashCode(); + h$ *= 1000003; + h$ ^= bootstrap.hashCode(); + return h$; + } + + static final class Builder extends NewChannelAction.Builder { + private Duration delay; + private O outboundMessage; + private Protocol protocol; + private ActionHandler actionHandler; + private Bootstrap bootstrap; + Builder() { + } + @Override + public NewChannelAction.Builder delay(Duration delay) { + if (delay == null) { + throw new NullPointerException("Null delay"); + } + this.delay = delay; + return this; + } + @Override + public NewChannelAction.Builder outboundMessage(O outboundMessage) { + if (outboundMessage == null) { + throw new NullPointerException("Null outboundMessage"); + } + this.outboundMessage = outboundMessage; + return this; + } + @Override + public NewChannelAction.Builder protocol(Protocol protocol) { + if (protocol == null) { + throw new NullPointerException("Null protocol"); + } + this.protocol = protocol; + return this; + } + @Override + public NewChannelAction.Builder actionHandler(ActionHandler actionHandler) { + if (actionHandler == null) { + throw new NullPointerException("Null actionHandler"); + } + this.actionHandler = actionHandler; + return this; + } + @Override + public NewChannelAction.Builder bootstrap(Bootstrap bootstrap) { + if (bootstrap == null) { + throw new NullPointerException("Null bootstrap"); + } + this.bootstrap = bootstrap; + return this; + } + @Override + public NewChannelAction build() { + String missing = ""; + if (this.delay == null) { + missing += " delay"; + } + if (this.outboundMessage == null) { + missing += " outboundMessage"; + } + if (this.protocol == null) { + missing += " protocol"; + } + if (this.actionHandler == null) { + missing += " actionHandler"; + } + if (this.bootstrap == null) { + missing += " bootstrap"; + } + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing required properties:" + missing); + } + return new AutoValue_NewChannelAction( + this.delay, + this.outboundMessage, + this.protocol, + this.actionHandler, + this.bootstrap); + } + } + +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java new file mode 100644 index 00000000000..26f560b145b --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java @@ -0,0 +1,118 @@ + + +package google.registry.monitoring.blackbox; + +import io.netty.channel.Channel; +import javax.annotation.Generated; +import org.joda.time.Duration; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_ProbingAction extends ProbingAction { + + private final Duration delay; + + private final O outboundMessage; + + private final Channel channel; + + private final Protocol protocol; + + private final ActionHandler actionHandler; + + AutoValue_ProbingAction( + Duration delay, + O outboundMessage, + Channel channel, + Protocol protocol, + ActionHandler actionHandler) { + if (delay == null) { + throw new NullPointerException("Null delay"); + } + this.delay = delay; + if (outboundMessage == null) { + throw new NullPointerException("Null outboundMessage"); + } + this.outboundMessage = outboundMessage; + if (channel == null) { + throw new NullPointerException("Null channel"); + } + this.channel = channel; + if (protocol == null) { + throw new NullPointerException("Null protocol"); + } + this.protocol = protocol; + if (actionHandler == null) { + throw new NullPointerException("Null actionHandler"); + } + this.actionHandler = actionHandler; + } + + @Override + Duration delay() { + return delay; + } + + @Override + O outboundMessage() { + return outboundMessage; + } + + @Override + Channel channel() { + return channel; + } + + @Override + Protocol protocol() { + return protocol; + } + + @Override + ActionHandler actionHandler() { + return actionHandler; + } + + @Override + public String toString() { + return "ProbingAction{" + + "delay=" + delay + ", " + + "outboundMessage=" + outboundMessage + ", " + + "channel=" + channel + ", " + + "protocol=" + protocol + ", " + + "actionHandler=" + actionHandler + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof ProbingAction) { + ProbingAction that = (ProbingAction) o; + return this.delay.equals(that.delay()) + && this.outboundMessage.equals(that.outboundMessage()) + && this.channel.equals(that.channel()) + && this.protocol.equals(that.protocol()) + && this.actionHandler.equals(that.actionHandler()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= delay.hashCode(); + h$ *= 1000003; + h$ ^= outboundMessage.hashCode(); + h$ *= 1000003; + h$ ^= channel.hashCode(); + h$ *= 1000003; + h$ ^= protocol.hashCode(); + h$ *= 1000003; + h$ ^= actionHandler.hashCode(); + return h$; + } + +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java new file mode 100644 index 00000000000..3247cbdd310 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java @@ -0,0 +1,153 @@ + + +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_Protocol extends Protocol { + + private final String name; + + private final int port; + + private final String host; + + private final ImmutableList> handlerProviders; + + private AutoValue_Protocol( + String name, + int port, + String host, + ImmutableList> handlerProviders) { + this.name = name; + this.port = port; + this.host = host; + this.handlerProviders = handlerProviders; + } + + @Override + String name() { + return name; + } + + @Override + int port() { + return port; + } + + @Override + String host() { + return host; + } + + @Override + ImmutableList> handlerProviders() { + return handlerProviders; + } + + @Override + public String toString() { + return "Protocol{" + + "name=" + name + ", " + + "port=" + port + ", " + + "host=" + host + ", " + + "handlerProviders=" + handlerProviders + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Protocol) { + Protocol that = (Protocol) o; + return this.name.equals(that.name()) + && this.port == that.port() + && this.host.equals(that.host()) + && this.handlerProviders.equals(that.handlerProviders()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= name.hashCode(); + h$ *= 1000003; + h$ ^= port; + h$ *= 1000003; + h$ ^= host.hashCode(); + h$ *= 1000003; + h$ ^= handlerProviders.hashCode(); + return h$; + } + + static final class Builder extends Protocol.Builder { + private String name; + private Integer port; + private String host; + private ImmutableList> handlerProviders; + Builder() { + } + @Override + Protocol.Builder name(String name) { + if (name == null) { + throw new NullPointerException("Null name"); + } + this.name = name; + return this; + } + @Override + Protocol.Builder port(int port) { + this.port = port; + return this; + } + @Override + Protocol.Builder host(String host) { + if (host == null) { + throw new NullPointerException("Null host"); + } + this.host = host; + return this; + } + @Override + Protocol.Builder handlerProviders(ImmutableList> handlerProviders) { + if (handlerProviders == null) { + throw new NullPointerException("Null handlerProviders"); + } + this.handlerProviders = handlerProviders; + return this; + } + @Override + Protocol build() { + String missing = ""; + if (this.name == null) { + missing += " name"; + } + if (this.port == null) { + missing += " port"; + } + if (this.host == null) { + missing += " host"; + } + if (this.handlerProviders == null) { + missing += " handlerProviders"; + } + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing required properties:" + missing); + } + return new AutoValue_Protocol( + this.name, + this.port, + this.host, + this.handlerProviders); + } + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java new file mode 100644 index 00000000000..1437d600539 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -0,0 +1,52 @@ +// 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.monitoring.blackbox; + +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import java.util.function.Function; + +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { + + private ChannelPromise finished; + private Channel channel; + + @Override + public ChannelFuture apply(O outboundMessage) { + // Send the request to server. + channel.writeAndFlush(outboundMessage); + return finished; + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) { + channel = ctx.channel(); + finished = ctx.newPromise(); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, I InboundMessage) { + // Response received, validate it, register metrics, etc. + // Once everything is done, mark the promise as success; + + finished.setSuccess(); + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java new file mode 100644 index 00000000000..61699ce033c --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java @@ -0,0 +1,8 @@ +package google.registry.monitoring.blackbox; + +public class Main { + public static void main(String[] args) { + System.out.println("Hello, world!"); + + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..ce452e19bf0 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,70 @@ +package google.registry.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOutboundInvoker; +import io.netty.channel.ChannelPromise; +import io.netty.channel.DefaultChannelPromise; +import io.netty.channel.socket.nio.NioSocketChannel; +import org.joda.time.Duration; + +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + abstract Bootstrap bootstrap(); + + private Channel channel; + + @Override + public Channel channel() { + return this.channel; + } + + @Override + public ChannelFuture call() { + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(NioSocketChannel outboundChannel) + throws Exception { + addHandlers( + outboundChannel.pipeline(), protocol().handlerProviders()); + } + }); + + ChannelFuture connectionFuture = bootstrap.connect(protocol().host(), protocol().port()); + ChannelPromise finished = null; + + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + this.channel = channelFuture.channel(); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + + } + } + ); + return finished; + } + + public static ProbingAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder(); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder outboundMessage(O value); + + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 8173ba6baee..2ccf818a57a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,303 +14,126 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; -import io.netty.util.AttributeKey; import io.netty.util.HashedWheelTimer; import io.netty.util.Timer; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; import javax.inject.Provider; -import org.joda.time.Duration; /** - * AutoValue class that represents action generated by {@link ProbingStep} + *Class that represents given action in sequence of probing * - *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when - * the task has been completed

- * - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type - * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall - * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the - * details of that connection.

- * - *

In its build, if there is no channel supplied, it will create a channel from the attributes - * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when - * informed that the connection is successful. If the channel is supplied, the connection future is - * automatically set to successful.

*/ -@AutoValue -public abstract class ProbingAction implements Callable { + +public abstract class ProbingAction implements Callable { /** - * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when - * channel is active. - */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey - .valueOf("CONNECTION_FUTURE_KEY"); - /** - * {@link AttributeKey} in channel that gives the information of the channel's host. - */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey - .valueOf("REMOTE_ADDRESS_KEY"); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** - * {@link Timer} that rate limits probing + * timer that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); - } - /** - * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified - * - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified + * @return actual Duration of delay */ - private static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } + abstract Duration delay(); /** - * Actual {@link Duration} of this delay + * @return message to send to server */ - public abstract Duration delay(); + abstract O outboundMessage(); /** - * {@link OutboundMessageType} instance that we write and flush down pipeline to server + * @return Channel object that represents connection between prober client and server */ - public abstract OutboundMessageType outboundMessage(); + abstract Channel channel(); /** - * {@link Channel} object that either created by or passed into this {@link ProbingAction} - * instance + * @return The Protocol instance that represents action to be tested by this part in sequences */ - public abstract Channel channel(); + abstract Protocol protocol(); /** - * The {@link Protocol} instance that specifies type of connection + * @return The requisite instance of Action Handler, which is always the last Handler in the pipeline */ - public abstract Protocol protocol(); + abstract Bootstrap bootstrap(); + abstract ActionHandler actionHandler(); /** - * The hostname of the remote host we have a connection or will make a connection to + * + * @return Builder for the ProbingAction Class */ - public abstract String host(); /** - * Performs the work of the actual action. - * - *

First, checks if channel is active by setting a listener to perform the bulk of the work - * when the connection future is successful.

- * - *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

- * - *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

- * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. + * The method that calls the ActionHandler to send a message down the channel pipeline + * @return future that denotes when the action has been successfully performed */ @Override public ChannelFuture call() { - //ChannelPromise that we return + // Add the Handlers from the run the action + // (with delay if present), and remove the ActionHandler afterwards, + // in case the channel is to be reused later. + ChannelPromise finished = channel().newPromise(); + timer.newTimeout(timeout -> + // Retry logic may also be added here. + actionHandler().apply(outboundMessage()).addListeners( + future -> finished.setSuccess()), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; + } - //Ensures channel has been set up with connection future as an attribute - checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + abstract static class Builder, P extends ProbingAction> { - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture connectionFuture) -> { - if (connectionFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); + public abstract B delay(Duration value); - ActionHandler actionHandler; - try { - actionHandler = channel().pipeline().get(ActionHandler.class); - } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw - // an UndeterminedStateException - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + public abstract B outboundMessage(O value); - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture unusedFutureWriteAndFlush = - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> { - if (future.isSuccess()) { - ChannelFuture unusedFuture = finished.setSuccess(); - } else { - ChannelFuture unusedFuture = finished.setFailure(future.cause()); - } - }, - //If we don't have a persistent connection, close the connection to this - // channel - future -> { - if (!protocol().persistentConnection()) { + public abstract B protocol(Protocol value); - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) { - logger.atInfo() - .log("Closed stale channel. Moving on to next ProbingStep"); - } else { - logger.atWarning() - .log( - "Could not close channel. Stale connection still exists" - + "."); - } - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(connectionFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } + public abstract B actionHandler(ActionHandler value); - @Override - public final String toString() { - return String.format( - "ProbingAction with delay: %d\n" - + "outboundMessage: %s\n" - + "protocol: %s\n" - + "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); + public abstract P build(); } - /** - * {@link AutoValue.Builder} that does work of creating connection when not already present. + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified */ - @AutoValue.Builder - public abstract static class Builder { - - private Bootstrap bootstrap; - - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; + static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); } + } - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setHost(String value); - - public abstract Builder setChannel(Channel channel); - - abstract Protocol protocol(); - - abstract Channel channel(); - - abstract String host(); - abstract ProbingAction autoBuild(); - public ProbingAction build() { - // Sets SocketAddress to bind to. - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - address = new LocalAddress(host()); - } + /** + * @param channelPipeline is pipeline associated with channel we want to remove handlers from + * removes all handlers from pipeline + */ + static void removeHandlers(ChannelPipeline channelPipeline) { + while (channelPipeline.first() != null) { + channelPipeline.removeFirst(); + } + } - //Sets channel supplied or to be created. - Channel channel; - try { - channel = channel(); - } catch (IllegalStateException e) { - channel = null; - } - checkArgument(channel == null ^ bootstrap == null, - "One and only one of bootstrap and channel must be supplied."); - //If a channel is supplied, nothing is needed to be done - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel == null) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); +} - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } - //now we can actually build the ProbingAction - return autoBuild(); - } - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java new file mode 100644 index 00000000000..73dfd778d69 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox; + +public class ProbingFlows { + + public static void main(String[] args) { + ProbingSequence sequence = new ProbingSequence + .Builder() + .addStep(new ProbingStep()) + .build(); + + sequence.start(); + + + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 7f97f8bd519..7c14d9f0bf0 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -1,77 +1,22 @@ -// Copyright 2019 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.monitoring.blackbox; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.EventLoopGroup; - -/** - * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. - * - * - *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} - * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one - * is the first repeated step.

- * - *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once - * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest - * of the work.

- */ -public class ProbingSequence { - +class ProbingSequence { private ProbingStep firstStep; - /** - * Each {@link ProbingSequence} requires a start token to begin running. - */ - private Token startToken; - - private ProbingSequence(ProbingStep firstStep, Token startToken) { - this.firstStep = firstStep; - this.startToken = startToken; - } - public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + // create a new unique token; + Token token = new TestToken<>(); + firstStep.accept(token); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link - * Bootstrap}. + * Builder that sequentially adds steps */ - public static class Builder { - + static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - - private Token startToken; - public Builder(Token startToken) { - this.startToken = startToken; - } - - /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, built, and pointed to by - * the previous {@link ProbingStep} added. - */ public Builder addStep(ProbingStep step) { - if (currentStep == null) { firstStep = step; } else { @@ -80,29 +25,18 @@ public Builder addStep(ProbingStep step) { currentStep = step; return this; - } - /** - * We take special note of the first repeated step. - */ - public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; - return this; } - /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private - * constructor to create {@link ProbingSequence}. - */ public ProbingSequence build() { - if (firstRepeatedStep == null) { - firstRepeatedStep = firstStep; - } - - currentStep.nextStep(firstRepeatedStep); - currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + currentStep.nextStep(firstStep); + return new ProbingSequence(this.firstStep); } + + } + + private ProbingSequence(ProbingStep firstStep) { + this.firstStep = firstStep; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 35bb141246a..2e2e3575d07 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -1,195 +1,60 @@ -// Copyright 2019 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.monitoring.blackbox; import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import java.util.function.Consumer; -import org.joda.time.Duration; - -/** - * {@link AutoValue} class that represents generator of actions performed at each step in {@link - * ProbingSequence}. - * - *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} - * instances. It then modifies these components on each loop iteration with the consumed {@link - * Token} and from that, generates a new {@link ProbingAction} to call.

- */ -@AutoValue -public abstract class ProbingStep implements Consumer { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * Necessary boolean to inform when to obtain next {@link Token} - */ - protected boolean isLastStep = false; - private ProbingStep nextStep; - - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); - } - /** - * Time delay duration between actions. - */ - abstract Duration duration(); - - /** - * {@link Protocol} type for this step. - */ - abstract Protocol protocol(); - - /** - * {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. - */ - abstract OutboundMessageType messageTemplate(); - - /** - * {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation - * of new channels. - */ - abstract Bootstrap bootstrap(); - - void lastStep() { - isLastStep = true; - } - void nextStep(ProbingStep step) { +public class ProbingStep implements Consumer> { + + private ProbingStep nextStep; + + public void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + public ProbingStep nextStep() { return this.nextStep; } - /** - * Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} - */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { - OutboundMessageType message = token.modifyMessage(messageTemplate()); - ProbingAction.Builder probingActionBuilder = ProbingAction.builder() - .setDelay(duration()) - .setProtocol(protocol()) - .setOutboundMessage(message) - .setHost(token.host()); - - if (token.channel() != null) { - probingActionBuilder.setChannel(token.channel()); - } else { - probingActionBuilder.setBootstrap(bootstrap()); - } - - return probingActionBuilder.build(); - } - /** - * On the last step, gets the next {@link Token}. Otherwise, uses the same one. - */ - private Token generateNextToken(Token token) { - return isLastStep ? token.next() : token; + + private ProbingAction generateAction(Token token) { + // Construct a new ProbingAction and return it. + // The action is only used for one invocation + // and uses the UniqueToken provided in the argument, to + // populate fields in the action. The UniqueToken contains + // all the information needed to create an action, including + // for example the test domain name to be created/deleted and + // the channel to reuse (for ExistingChannelActions). + + return NewChannelAction.builder() + .protocol(token.protocol()) + .outboundMessage(token.message()) + .actionHandler(token.actionHandler()) + .delay(token.DEFAULT_DURATION) + .build(); + } + private Token generateNextToken(Token token) { + // Given the input token, we should be able to deduce what + // this the token for the following steps to use. If this + // step generates an action to create a domain, and the next + // one checks for its existence, the domain contained in the + // token should not change. If this is the last step in a loop + // on the other hand, the next token should contain a new + // domain name for the next loop. + return token.next(); - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the - * action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is completed is - * marked as a success, we note a success. Otherwise, if the cause of failure will either be a - * failure or error.

- */ - @Override - public void accept(Token token) { - ProbingAction currentAction; - //attempt to generate new action. On error, move on to next step - try { - currentAction = generateAction(token); - } catch (UndeterminedStateException e) { - logger.atWarning().withCause(e).log("Error in Action Generation"); - nextStep.accept(generateNextToken(token)); - return; - } - - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch (Exception e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; - } - - future.addListener(f -> { - if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success - logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - - } else { - //On a failed result, we log the failure and note either a failure or error - logger.atSevere().withCause(f.cause()).log("Did not result in future success"); - } - - if (protocol().persistentConnection()) { - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - } - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - - }); } @Override - public final String toString() { - return String.format("ProbingStep with Protocol: %s\n" - + "OutboundMessage: %s\n", - protocol(), - messageTemplate().getClass().getName()); + public void accept(Token token) { + ChannelFuture future = generateAction(token).call(); + future.addListener(f -> nextStep().accept(generateNextToken(token))); } - /** - * Default {@link AutoValue.Builder} for {@link ProbingStep}. - */ - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setDuration(Duration value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setMessageTemplate(OutboundMessageType value); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract ProbingStep build(); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index ea2a6130380..ca18213acf6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -16,65 +16,46 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; import javax.inject.Provider; -/** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. - */ @AutoValue public abstract class Protocol { + final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - /** - * {@link AttributeKey} that lets channel reference {@link Protocol} that created it. - */ - public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - - public static Builder builder() { - return new AutoValue_Protocol.Builder(); - } + /** Protocol name. */ + abstract String name(); - public abstract String name(); + /** Port to bind to at remote host*/ + abstract int port(); - public abstract int port(); + abstract String host(); - /** - * The {@link ChannelHandler} providers to use for the protocol, in order. - */ + /** The {@link ChannelHandler} providers to use for the protocol, in order. */ abstract ImmutableList> handlerProviders(); - /** - * Boolean that notes if connection associated with Protocol is persistent. - */ - abstract boolean persistentConnection(); - - @Override - public final String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); + static Protocol.Builder builder() { + return new AutoValue_Protocol.Builder(); + } + + public static Protocol defaultImplementation(){ + return Protocol.builder().name("Default").port(8080).host("127.0.0.1").handlerProviders(ImmutableList.of()).build(); } - /** - * Default {@link AutoValue.Builder} for {@link Protocol}. - */ @AutoValue.Builder - public abstract static class Builder { + public static abstract class Builder { - public abstract Builder setName(String value); + abstract Builder name(String value); - public abstract Builder setPort(int num); + abstract Builder host(String value); - public abstract Builder setHandlerProviders( - ImmutableList> providers); + abstract Builder port(int num); - public abstract Builder setPersistentConnection(boolean value); + abstract Builder handlerProviders(ImmutableList> providers); - public abstract Protocol build(); + abstract Protocol build(); } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java new file mode 100644 index 00000000000..0fc57f8967e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java @@ -0,0 +1,28 @@ +package google.registry.monitoring.blackbox; + + +public class TestToken extends Token { + @Override + public Protocol protocol(){ + return Protocol.defaultImplementation(); + } + + @Override + public Token next() { + return this; + } + + @Override + public O message() { + return (O) this.domainName; + } + + @Override + public ActionHandler actionHandler() { + return new ActionHandler(); + } + + public static TestToken generateNext() { + return new TestToken(); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java new file mode 100644 index 00000000000..c20ed770888 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java @@ -0,0 +1,20 @@ +package google.registry.monitoring.blackbox; + +import org.joda.time.Duration; + +abstract class Token { + public static final Duration DEFAULT_DURATION = new Duration(2000L); + protected String domainName; + + abstract Protocol protocol(); + abstract Token next(); + abstract O message(); + abstract ActionHandler actionHandler(); + + private static String newDomainName(String previousName) { + return String.format("prober-%d", System.currentTimeMillis()); + } + + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java new file mode 100644 index 00000000000..b3d22bfd24d --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java @@ -0,0 +1,16 @@ +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package google.registry.monitoring.blackbox; \ No newline at end of file From d2cb08db6df24bdb6f7c701c55a04088ecc9d714 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 21 Jun 2019 14:23:16 -0400 Subject: [PATCH 002/337] Deleted unfinished features. Added ActionHandler and its Unit Tests. --- .../monitoring/blackbox/ActionHandler.java | 31 +++- .../registry/monitoring/blackbox/Main.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 70 --------- .../monitoring/blackbox/ProbingAction.java | 139 ------------------ .../monitoring/blackbox/ProbingFlows.java | 15 -- .../monitoring/blackbox/ProbingSequence.java | 42 ------ .../monitoring/blackbox/ProbingStep.java | 61 -------- .../monitoring/blackbox/Protocol.java | 61 -------- .../monitoring/blackbox/TestToken.java | 28 ---- .../registry/monitoring/blackbox/Token.java | 20 --- .../blackbox/TestActionHandler.java | 84 +++++++++++ .../monitoring/blackbox/package-info.java | 16 ++ 12 files changed, 124 insertions(+), 444 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/package-info.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java index 1437d600539..92e89102eac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -20,33 +20,50 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import java.util.function.Function; +import javax.inject.Inject; -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { private ChannelPromise finished; private Channel channel; + @Inject + public ActionHandler() {} + @Override - public ChannelFuture apply(O outboundMessage) { - // Send the request to server. + public ChannelFuture apply(Object outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + channel.writeAndFlush(outboundMessage); return finished; } @Override public void handlerAdded(ChannelHandlerContext ctx) { + //Once handler is added to channel pipeline, initialize channel and future for this handler channel = ctx.channel(); finished = ctx.newPromise(); } @Override - protected void channelRead0(ChannelHandlerContext ctx, I InboundMessage) { - // Response received, validate it, register metrics, etc. - // Once everything is done, mark the promise as success; + protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { + //Only purpose of Handler is to mark future as a success finished.setSuccess(); } + /** + *Both methods are only used for testing + */ + + public Channel getChannel() { + return channel; + } + + public ChannelPromise getFinished() { + return finished; + } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java index 61699ce033c..c093b9274f8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java @@ -2,7 +2,6 @@ public class Main { public static void main(String[] args) { - System.out.println("Hello, world!"); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index ce452e19bf0..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,70 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOutboundInvoker; -import io.netty.channel.ChannelPromise; -import io.netty.channel.DefaultChannelPromise; -import io.netty.channel.socket.nio.NioSocketChannel; -import org.joda.time.Duration; - -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - abstract Bootstrap bootstrap(); - - private Channel channel; - - @Override - public Channel channel() { - return this.channel; - } - - @Override - public ChannelFuture call() { - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(NioSocketChannel outboundChannel) - throws Exception { - addHandlers( - outboundChannel.pipeline(), protocol().handlerProviders()); - } - }); - - ChannelFuture connectionFuture = bootstrap.connect(protocol().host(), protocol().port()); - ChannelPromise finished = null; - - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - this.channel = channelFuture.channel(); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - - } - } - ); - return finished; - } - - public static ProbingAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder(); - } - - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { - - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder outboundMessage(O value); - - } - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java deleted file mode 100644 index 2ccf818a57a..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ /dev/null @@ -1,139 +0,0 @@ -// 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.monitoring.blackbox; - - -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableList; -import io.netty.bootstrap.Bootstrap; -import java.util.concurrent.TimeUnit; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; -import javax.inject.Provider; - -/** - *Class that represents given action in sequence of probing - * - */ - - -public abstract class ProbingAction implements Callable { - - /** - * timer that rate limits probing - */ - private static final Timer timer = new HashedWheelTimer(); - - /** - * @return actual Duration of delay - */ - abstract Duration delay(); - - /** - * @return message to send to server - */ - abstract O outboundMessage(); - - /** - * @return Channel object that represents connection between prober client and server - */ - abstract Channel channel(); - - /** - * @return The Protocol instance that represents action to be tested by this part in sequences - */ - abstract Protocol protocol(); - - /** - * @return The requisite instance of Action Handler, which is always the last Handler in the pipeline - */ - abstract Bootstrap bootstrap(); - abstract ActionHandler actionHandler(); - - /** - * - * @return Builder for the ProbingAction Class - */ - - /** - * The method that calls the ActionHandler to send a message down the channel pipeline - * @return future that denotes when the action has been successfully performed - */ - @Override - public ChannelFuture call() { - // Add the Handlers from the run the action - // (with delay if present), and remove the ActionHandler afterwards, - // in case the channel is to be reused later. - - ChannelPromise finished = channel().newPromise(); - timer.newTimeout(timeout -> - // Retry logic may also be added here. - actionHandler().apply(outboundMessage()).addListeners( - future -> finished.setSuccess()), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - return finished; - } - - abstract static class Builder, P extends ProbingAction> { - - public abstract B delay(Duration value); - - public abstract B outboundMessage(O value); - - public abstract B protocol(Protocol value); - - public abstract B actionHandler(ActionHandler value); - - public abstract P build(); - } - /** - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified - */ - static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } - - - - /** - * @param channelPipeline is pipeline associated with channel we want to remove handlers from - * removes all handlers from pipeline - */ - static void removeHandlers(ChannelPipeline channelPipeline) { - while (channelPipeline.first() != null) { - channelPipeline.removeFirst(); - } - } - - - - -} - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java deleted file mode 100644 index 73dfd778d69..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java +++ /dev/null @@ -1,15 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingFlows { - - public static void main(String[] args) { - ProbingSequence sequence = new ProbingSequence - .Builder() - .addStep(new ProbingStep()) - .build(); - - sequence.start(); - - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java deleted file mode 100644 index 7c14d9f0bf0..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ /dev/null @@ -1,42 +0,0 @@ -package google.registry.monitoring.blackbox; - -class ProbingSequence { - private ProbingStep firstStep; - - public void start() { - // create a new unique token; - Token token = new TestToken<>(); - firstStep.accept(token); - } - - /** - * Builder that sequentially adds steps - */ - static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - - public Builder addStep(ProbingStep step) { - if (currentStep == null) { - firstStep = step; - } else { - currentStep.nextStep(step); - } - - currentStep = step; - return this; - - } - - public ProbingSequence build() { - currentStep.nextStep(firstStep); - return new ProbingSequence(this.firstStep); - } - - } - - private ProbingSequence(ProbingStep firstStep) { - this.firstStep = firstStep; - } -} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java deleted file mode 100644 index 2e2e3575d07..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ /dev/null @@ -1,61 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import java.util.function.Consumer; - - -public class ProbingStep implements Consumer> { - - private ProbingStep nextStep; - - public void nextStep(ProbingStep step) { - this.nextStep = step; - } - - public ProbingStep nextStep() { - return this.nextStep; - } - - - - private ProbingAction generateAction(Token token) { - // Construct a new ProbingAction and return it. - // The action is only used for one invocation - // and uses the UniqueToken provided in the argument, to - // populate fields in the action. The UniqueToken contains - // all the information needed to create an action, including - // for example the test domain name to be created/deleted and - // the channel to reuse (for ExistingChannelActions). - - return NewChannelAction.builder() - .protocol(token.protocol()) - .outboundMessage(token.message()) - .actionHandler(token.actionHandler()) - .delay(token.DEFAULT_DURATION) - .build(); - - } - private Token generateNextToken(Token token) { - // Given the input token, we should be able to deduce what - // this the token for the following steps to use. If this - // step generates an action to create a domain, and the next - // one checks for its existence, the domain contained in the - // token should not change. If this is the last step in a loop - // on the other hand, the next token should contain a new - // domain name for the next loop. - return token.next(); - - } - - @Override - public void accept(Token token) { - ChannelFuture future = generateAction(token).call(); - future.addListener(f -> nextStep().accept(generateNextToken(token))); - } - - -} - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java deleted file mode 100644 index ca18213acf6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ /dev/null @@ -1,61 +0,0 @@ -// 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableList; -import io.netty.util.AttributeKey; -import io.netty.channel.ChannelHandler; -import javax.inject.Provider; - -@AutoValue -public abstract class Protocol { - final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - - /** Protocol name. */ - abstract String name(); - - /** Port to bind to at remote host*/ - abstract int port(); - - abstract String host(); - - /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - abstract ImmutableList> handlerProviders(); - - static Protocol.Builder builder() { - return new AutoValue_Protocol.Builder(); - } - - public static Protocol defaultImplementation(){ - return Protocol.builder().name("Default").port(8080).host("127.0.0.1").handlerProviders(ImmutableList.of()).build(); - } - - @AutoValue.Builder - public static abstract class Builder { - - abstract Builder name(String value); - - abstract Builder host(String value); - - abstract Builder port(int num); - - abstract Builder handlerProviders(ImmutableList> providers); - - abstract Protocol build(); - } - - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java deleted file mode 100644 index 0fc57f8967e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java +++ /dev/null @@ -1,28 +0,0 @@ -package google.registry.monitoring.blackbox; - - -public class TestToken extends Token { - @Override - public Protocol protocol(){ - return Protocol.defaultImplementation(); - } - - @Override - public Token next() { - return this; - } - - @Override - public O message() { - return (O) this.domainName; - } - - @Override - public ActionHandler actionHandler() { - return new ActionHandler(); - } - - public static TestToken generateNext() { - return new TestToken(); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java deleted file mode 100644 index c20ed770888..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java +++ /dev/null @@ -1,20 +0,0 @@ -package google.registry.monitoring.blackbox; - -import org.joda.time.Duration; - -abstract class Token { - public static final Duration DEFAULT_DURATION = new Duration(2000L); - protected String domainName; - - abstract Protocol protocol(); - abstract Token next(); - abstract O message(); - abstract ActionHandler actionHandler(); - - private static String newDomainName(String previousName) { - return String.format("prober-%d", System.currentTimeMillis()); - } - - - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java new file mode 100644 index 00000000000..091fbbbf9a4 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java @@ -0,0 +1,84 @@ +// 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelPromise; +import io.netty.channel.embedded.EmbeddedChannel; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + + +/** Unit tests for {@link ActionHandler}. */ +@RunWith(JUnit4.class) +public class TestActionHandler { + + private final ActionHandler actionHandler = new ActionHandler(); + private EmbeddedChannel channel; + + @Before + public void setup() { + channel = new EmbeddedChannel(actionHandler); + } + + @Test + public void testHandler_Params() { + //initial check on Channel Activity + assertThat(channel.isActive()).isTrue(); + + + //Ensures channel Handler points to is right what + assertThat(actionHandler.getChannel()).isEqualTo(channel); + } + + @Test + public void testHandler_Behavior() { + //initial check on Channel Activity + assertThat(channel.isActive()).isTrue(); + + + ByteBuf outboundBuffer = Unpooled.copyInt(64); + + //Use ActionHandler's write method to check if the future returned is accurate + //and that it accurately writes out the inputBuffer + assertThat(actionHandler.apply(outboundBuffer)).isEqualTo(actionHandler.getFinished()); + assertThat(channel.outboundMessages().poll()).isEqualTo(outboundBuffer); + + //Creates Promise that is set to success when something changes on actionHandler's future + ChannelPromise testPromise = channel.newPromise(); + actionHandler.getFinished().addListener(f -> testPromise.setSuccess()); + + //Ensure that before reading inbound data, actionHandler's future stays inactive + assertThat(testPromise.isSuccess()).isFalse(); + + ByteBuf inputBuffer = Unpooled.copyInt(128); + + //Check that ActionHandler doesn't do anything to inbound Buffer + assertThat(channel.writeInbound(inputBuffer)).isFalse(); + + + //ensures that actionHandler's future's listener is active and that it is set to success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(actionHandler.getFinished().isSuccess()).isTrue(); + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java new file mode 100644 index 00000000000..b3d22bfd24d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java @@ -0,0 +1,16 @@ +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package google.registry.monitoring.blackbox; \ No newline at end of file From 7c61fce7057f7dbd58436b3589d866c5fd832d84 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 21 Jun 2019 14:45:36 -0400 Subject: [PATCH 003/337] Included prober subproject in settings.gradle --- settings.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings.gradle b/settings.gradle index 9b2d11de8da..0cd8f4dd707 100644 --- a/settings.gradle +++ b/settings.gradle @@ -36,3 +36,5 @@ include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' +include 'prober' + From 6dee46196388249c9fabd451f189bc03152b1761 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 24 Jun 2019 12:18:55 -0400 Subject: [PATCH 004/337] Added Protocol Class and its Basic Unit Tests --- .../monitoring/blackbox/ActionHandler.java | 69 ------------ .../monitoring/blackbox/Protocol.java | 75 +++++++++++++ .../blackbox/handlers/ActionHandler.java | 100 +++++------------- .../monitoring/blackbox/TestProtocol.java | 70 ++++++++++++ 4 files changed, 173 insertions(+), 141 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java deleted file mode 100644 index 92e89102eac..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ /dev/null @@ -1,69 +0,0 @@ -// 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.monitoring.blackbox; - -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import java.util.function.Function; -import javax.inject.Inject; - -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { - - private ChannelPromise finished; - private Channel channel; - - @Inject - public ActionHandler() {} - - @Override - public ChannelFuture apply(Object outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline - - channel.writeAndFlush(outboundMessage); - return finished; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) { - //Once handler is added to channel pipeline, initialize channel and future for this handler - channel = ctx.channel(); - finished = ctx.newPromise(); - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { - //Only purpose of Handler is to mark future as a success - - finished.setSuccess(); - } - - /** - *Both methods are only used for testing - */ - - public Channel getChannel() { - return channel; - } - - public ChannelPromise getFinished() { - return finished; - } - -} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java new file mode 100644 index 00000000000..3ddecba5af7 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -0,0 +1,75 @@ +// 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; +import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; +import javax.inject.Provider; + +@AutoValue +public abstract class Protocol { + + /** + * Default names associated with each protocol + */ + final static String EPP_PROTOCOL_NAME = "EPP"; + final static String DNS_PROTOCOL_NAME = "DNS"; + final static String WHOIS_PROTOCOL_NAME = "WHOIS"; + final static String RDAP_PROTOCOL_NAME = "RDAP"; + + final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + public boolean PERSISTENT_CONNECTION = name() == EPP_PROTOCOL_NAME; + /** + * @return name of Protocol. + */ + abstract String name(); + + /** + * @return Port to bind to at remote host + */ + abstract int port(); + + /** + * @return hostname to connect to + */ + abstract String host(); + + /** The {@link ChannelHandler} providers to use for the protocol, in order. */ + abstract ImmutableList> handlerProviders(); + + /** Builds new Protocol from @AutoValue Builder implementation*/ + static Protocol.Builder builder() { + return new AutoValue_Protocol.Builder(); + } + + + @AutoValue.Builder + public static abstract class Builder { + + abstract Builder name(String value); + + abstract Builder host(String value); + + abstract Builder port(int num); + + abstract Builder handlerProviders(ImmutableList> providers); + + abstract Protocol build(); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 1e1a834231c..54c51749aaf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,100 +14,56 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; - -/** - * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline - * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler}, - * as it should only be passed in messages that implement the {@link InboundMessageType} - * interface.

- * - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a - * {@link ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has - * been read. Second, with any exception thrown, the connection is closed, and the ProbingAction - * governing this channel is informed of the error. If the error is an instance of a {@link - * FailureException} {@code finished} is marked as a failure with cause {@link FailureException}. If - * it is any other type of error, it is treated as an {@link UndeterminedStateException} and {@code - * finished} set as a failure with the same cause as what caused the exception. Lastly, if no error - * is thrown, we know the action completed as a success, and, as such, we mark {@code finished} as a - * success.

- * - *

Subclasses specify further work to be done for specific kinds of channel pipelines.

- */ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +import java.util.function.Function; +import javax.inject.Inject; - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { - /** - * {@link ChannelPromise} that informs {@link ProbingAction} if response has been received. - */ private ChannelPromise finished; + private Channel channel; - /** - * Returns initialized {@link ChannelPromise} to {@link ProbingAction}. - */ - public ChannelFuture getFinishedFuture() { + @Inject + public ActionHandler() {} + + @Override + public ChannelFuture apply(Object outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + + channel.writeAndFlush(outboundMessage); return finished; } - /** - * Initializes {@link ChannelPromise} - */ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler + channel = ctx.channel(); finished = ctx.newPromise(); } - /** - * Marks {@link ChannelPromise} as success - */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { + //Only purpose of Handler is to mark future as a success - ChannelFuture unusedFuture = finished.setSuccess(); + finished.setSuccess(); } /** - * Logs the channel and pipeline that caused error, closes channel, then informs {@link - * ProbingAction} listeners of error. + *Both methods are only used for testing */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atWarning().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); - - if (cause instanceof FailureException) { - //On FailureException, we know the response is a failure. - - //Since it wasn't a success, we still want to log to see what caused the FAILURE - logger.atInfo().log(cause.getMessage()); - - //As always, inform the ProbingStep that we successfully completed this action - ChannelFuture unusedFuture = finished.setFailure(cause); - } else { - //On UndeterminedStateException, we know the response type is an error. - - //Since it wasn't a success, we still log what caused the ERROR - logger.atWarning().log(cause.getMessage()); - ChannelFuture unusedFuture = finished.setFailure(cause); + public Channel getChannel() { + return channel; + } - //As this was an ERROR in performing the action, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } + public ChannelPromise getFinished() { + return finished; } + } + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java new file mode 100644 index 00000000000..8f35843cb4c --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java @@ -0,0 +1,70 @@ +package google.registry.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.TestModule.TestProtocolModule; +import google.registry.monitoring.blackbox.TestModule.TestComponent; +import com.google.common.collect.ImmutableList; +import io.netty.channel.ChannelHandler; +import javax.inject.Inject; +import javax.inject.Provider; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Basic unit test for Protocol Class + */ +@RunWith(JUnit4.class) +public class TestProtocol { + + /** + * Stores default values that constitute a Protocol + */ + private static final String HOST_NAME = "127.0.0.1"; + private static final int PORT_NUM = 0; + private static final String NAME = "Test"; + private static final ImmutableList> HANDLERS = ImmutableList.of(); + + /** + * Test Protocol that we build + */ + private Protocol protocol; + + /** + * + * @return Protocol implementation built using fields above + */ + static Protocol defaultImplementation() { + return Protocol.builder() + .host(HOST_NAME) + .port(PORT_NUM) + .name(NAME) + .handlerProviders(HANDLERS) + .build(); + } + + /** + * Stores default implementation into private protocol field + */ + private void basicProtocol() { + protocol = TestProtocol.defaultImplementation(); + } + + + /** + * Basic unit test that insures stored values in protocol are accurate + */ + @Test + public void testProtocolAttributes() { + basicProtocol(); + assertThat(protocol.host()).isEqualTo(HOST_NAME); + assertThat(protocol.port()).isEqualTo(PORT_NUM); + assertThat(protocol.name()).isEqualTo(NAME); + assertThat(protocol.handlerProviders()).isEqualTo(HANDLERS); + } + + + +} From b512cc6c1bbb4aedd8c708100f35481bb56a6fb2 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 28 Jun 2019 17:10:59 -0400 Subject: [PATCH 005/337] Added Changes Suggested by jianglai --- prober/build.gradle | 6 +- .../registry/monitoring/blackbox/Main.java | 7 -- .../monitoring/blackbox/Protocol.java | 71 +++++++++++++------ .../blackbox/handlers/ActionHandler.java | 49 ++++++++----- .../monitoring/blackbox/package-info.java | 1 - .../ActionHandlerTest.java} | 3 +- .../monitoring/blackbox/TestProtocol.java | 70 ------------------ .../monitoring/blackbox/package-info.java | 1 - 8 files changed, 86 insertions(+), 122 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Main.java rename prober/src/test/java/google/registry/monitoring/blackbox/{TestActionHandler.java => Handlers/ActionHandlerTest.java} (95%) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java diff --git a/prober/build.gradle b/prober/build.gradle index 33feefb7175..fe5e08a62f5 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'java' -createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Main') +createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') dependencies { @@ -30,7 +30,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] - compile project(':util') + //compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] @@ -42,7 +42,7 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - testCompile project(path: ':core', configuration: 'testRuntime') + //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java deleted file mode 100644 index c093b9274f8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java +++ /dev/null @@ -1,7 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Main { - public static void main(String[] args) { - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 3ddecba5af7..50a1d90a12c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -20,6 +20,11 @@ import io.netty.channel.ChannelHandler; import javax.inject.Provider; +/** + * Protocol Class packages all static variables necessary for a certain type of connection + * Both the host and the path can be changed for the same protocol + * Mainly packages the handlers necessary for the requisite channel pipeline + */ @AutoValue public abstract class Protocol { @@ -31,28 +36,49 @@ public abstract class Protocol { final static String WHOIS_PROTOCOL_NAME = "WHOIS"; final static String RDAP_PROTOCOL_NAME = "RDAP"; - final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - public boolean PERSISTENT_CONNECTION = name() == EPP_PROTOCOL_NAME; - /** - * @return name of Protocol. - */ - abstract String name(); + private String host; + private String path = ""; - /** - * @return Port to bind to at remote host - */ - abstract int port(); + /** Setter method for Protocol's host*/ + public Protocol host(String host) { + this.host = host; + return this; + } - /** - * @return hostname to connect to - */ - abstract String host(); + /** Getter method for Protocol's host*/ + public String host() { + return host; + } + + /** Setter method for Protocol's path*/ + public Protocol path(String path) { + this.path = path; + return this; + } + + /** Getter method for Protocol's path*/ + public String path() { + return path; + } + + /** If connection associated with Protocol is persistent, which is only EPP */ + public boolean persistentConnection() { + return name() == EPP_PROTOCOL_NAME; + } + + /** Protocol Name */ + public abstract String name(); + + /** Port to bind to at remote host */ + public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - abstract ImmutableList> handlerProviders(); + public abstract ImmutableList> handlerProviders(); + + + public abstract Builder toBuilder(); - /** Builds new Protocol from @AutoValue Builder implementation*/ - static Protocol.Builder builder() { + public static Protocol.Builder builder() { return new AutoValue_Protocol.Builder(); } @@ -60,16 +86,15 @@ static Protocol.Builder builder() { @AutoValue.Builder public static abstract class Builder { - abstract Builder name(String value); + public abstract Builder name(String value); - abstract Builder host(String value); + public abstract Builder port(int num); - abstract Builder port(int num); + public abstract Builder handlerProviders(ImmutableList> providers); - abstract Builder handlerProviders(ImmutableList> providers); - - abstract Protocol build(); + public abstract Protocol build(); } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 54c51749aaf..a4df56408b5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,56 +14,73 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.flogger.FluentLogger; +import com.google.common.flogger.StackSize; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.HttpResponse; import java.util.function.Function; import javax.inject.Inject; -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { +/** + * + * @param Generic Type of Inbound Message + * @param Generic Type of Outbound Message + * Abstract class that tells sends message down pipeline and + * and tells listeners to move on when the message is received. + */ +public abstract class ActionHandler extends SimpleChannelInboundHandler + implements Function { - private ChannelPromise finished; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + protected ChannelPromise finished; private Channel channel; - @Inject - public ActionHandler() {} + /** returns ChannelPromise for when inbound message is recieved + * a + * @param outboundMessage + * @return + */ @Override - public ChannelFuture apply(Object outboundMessage) { + public ChannelFuture apply(O outboundMessage) { // Sends request along Outbound Handlers on the Pipeline channel.writeAndFlush(outboundMessage); return finished; + + } + + public void resetFuture() { + finished = channel.newPromise(); } @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler + channel = ctx.channel(); finished = ctx.newPromise(); } @Override - protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { + public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ //Only purpose of Handler is to mark future as a success finished.setSuccess(); } - /** - *Both methods are only used for testing - */ - - public Channel getChannel() { - return channel; + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } - public ChannelPromise getFinished() { - return finished; - } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java index b3d22bfd24d..21c8764701c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java @@ -12,5 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -@javax.annotation.ParametersAreNonnullByDefault package google.registry.monitoring.blackbox; \ No newline at end of file diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java similarity index 95% rename from prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java rename to prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java index 091fbbbf9a4..01b93866b14 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java @@ -12,10 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.Handlers; import static com.google.common.truth.Truth.assertThat; +import google.registry.monitoring.blackbox.handlers.ActionHandler; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelPromise; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java deleted file mode 100644 index 8f35843cb4c..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java +++ /dev/null @@ -1,70 +0,0 @@ -package google.registry.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import google.registry.monitoring.blackbox.TestModule.TestProtocolModule; -import google.registry.monitoring.blackbox.TestModule.TestComponent; -import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; -import javax.inject.Inject; -import javax.inject.Provider; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Basic unit test for Protocol Class - */ -@RunWith(JUnit4.class) -public class TestProtocol { - - /** - * Stores default values that constitute a Protocol - */ - private static final String HOST_NAME = "127.0.0.1"; - private static final int PORT_NUM = 0; - private static final String NAME = "Test"; - private static final ImmutableList> HANDLERS = ImmutableList.of(); - - /** - * Test Protocol that we build - */ - private Protocol protocol; - - /** - * - * @return Protocol implementation built using fields above - */ - static Protocol defaultImplementation() { - return Protocol.builder() - .host(HOST_NAME) - .port(PORT_NUM) - .name(NAME) - .handlerProviders(HANDLERS) - .build(); - } - - /** - * Stores default implementation into private protocol field - */ - private void basicProtocol() { - protocol = TestProtocol.defaultImplementation(); - } - - - /** - * Basic unit test that insures stored values in protocol are accurate - */ - @Test - public void testProtocolAttributes() { - basicProtocol(); - assertThat(protocol.host()).isEqualTo(HOST_NAME); - assertThat(protocol.port()).isEqualTo(PORT_NUM); - assertThat(protocol.name()).isEqualTo(NAME); - assertThat(protocol.handlerProviders()).isEqualTo(HANDLERS); - } - - - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java index b3d22bfd24d..21c8764701c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java @@ -12,5 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -@javax.annotation.ParametersAreNonnullByDefault package google.registry.monitoring.blackbox; \ No newline at end of file From d048d3576f32a44fe3690ab6c9b4ba3c869984fd Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:06:18 -0400 Subject: [PATCH 006/337] Fixed Gitignore to take out AutoValue generated code --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 327b22fe2e7..199c4fe3979 100644 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,9 @@ nomulus.iws # Javascript output **/out/* +# AutoValue generated code +AutoValue_.*.java + ###################################################################### # Python Ignores From 95e9d6c79aacbd58001ce2a29a06a750588eaaac Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:07:59 -0400 Subject: [PATCH 007/337] Removed AutoValue java files --- .../blackbox/AutoValue_NewChannelAction.java | 181 ------------------ .../blackbox/AutoValue_ProbingAction.java | 118 ------------ .../blackbox/AutoValue_Protocol.java | 153 --------------- 3 files changed, 452 deletions(-) delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java deleted file mode 100644 index 6f818f03a28..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java +++ /dev/null @@ -1,181 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import io.netty.bootstrap.Bootstrap; -import javax.annotation.Generated; -import org.joda.time.Duration; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_NewChannelAction extends NewChannelAction { - - private final Duration delay; - - private final O outboundMessage; - - private final Protocol protocol; - - private final ActionHandler actionHandler; - - private final Bootstrap bootstrap; - - private AutoValue_NewChannelAction( - Duration delay, - O outboundMessage, - Protocol protocol, - ActionHandler actionHandler, - Bootstrap bootstrap) { - this.delay = delay; - this.outboundMessage = outboundMessage; - this.protocol = protocol; - this.actionHandler = actionHandler; - this.bootstrap = bootstrap; - } - - @Override - Duration delay() { - return delay; - } - - @Override - O outboundMessage() { - return outboundMessage; - } - - @Override - Protocol protocol() { - return protocol; - } - - @Override - ActionHandler actionHandler() { - return actionHandler; - } - - @Override - Bootstrap bootstrap() { - return bootstrap; - } - - @Override - public String toString() { - return "NewChannelAction{" - + "delay=" + delay + ", " - + "outboundMessage=" + outboundMessage + ", " - + "protocol=" + protocol + ", " - + "actionHandler=" + actionHandler + ", " - + "bootstrap=" + bootstrap - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof NewChannelAction) { - NewChannelAction that = (NewChannelAction) o; - return this.delay.equals(that.delay()) - && this.outboundMessage.equals(that.outboundMessage()) - && this.protocol.equals(that.protocol()) - && this.actionHandler.equals(that.actionHandler()) - && this.bootstrap.equals(that.bootstrap()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= delay.hashCode(); - h$ *= 1000003; - h$ ^= outboundMessage.hashCode(); - h$ *= 1000003; - h$ ^= protocol.hashCode(); - h$ *= 1000003; - h$ ^= actionHandler.hashCode(); - h$ *= 1000003; - h$ ^= bootstrap.hashCode(); - return h$; - } - - static final class Builder extends NewChannelAction.Builder { - private Duration delay; - private O outboundMessage; - private Protocol protocol; - private ActionHandler actionHandler; - private Bootstrap bootstrap; - Builder() { - } - @Override - public NewChannelAction.Builder delay(Duration delay) { - if (delay == null) { - throw new NullPointerException("Null delay"); - } - this.delay = delay; - return this; - } - @Override - public NewChannelAction.Builder outboundMessage(O outboundMessage) { - if (outboundMessage == null) { - throw new NullPointerException("Null outboundMessage"); - } - this.outboundMessage = outboundMessage; - return this; - } - @Override - public NewChannelAction.Builder protocol(Protocol protocol) { - if (protocol == null) { - throw new NullPointerException("Null protocol"); - } - this.protocol = protocol; - return this; - } - @Override - public NewChannelAction.Builder actionHandler(ActionHandler actionHandler) { - if (actionHandler == null) { - throw new NullPointerException("Null actionHandler"); - } - this.actionHandler = actionHandler; - return this; - } - @Override - public NewChannelAction.Builder bootstrap(Bootstrap bootstrap) { - if (bootstrap == null) { - throw new NullPointerException("Null bootstrap"); - } - this.bootstrap = bootstrap; - return this; - } - @Override - public NewChannelAction build() { - String missing = ""; - if (this.delay == null) { - missing += " delay"; - } - if (this.outboundMessage == null) { - missing += " outboundMessage"; - } - if (this.protocol == null) { - missing += " protocol"; - } - if (this.actionHandler == null) { - missing += " actionHandler"; - } - if (this.bootstrap == null) { - missing += " bootstrap"; - } - if (!missing.isEmpty()) { - throw new IllegalStateException("Missing required properties:" + missing); - } - return new AutoValue_NewChannelAction( - this.delay, - this.outboundMessage, - this.protocol, - this.actionHandler, - this.bootstrap); - } - } - -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java deleted file mode 100644 index 26f560b145b..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java +++ /dev/null @@ -1,118 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import io.netty.channel.Channel; -import javax.annotation.Generated; -import org.joda.time.Duration; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_ProbingAction extends ProbingAction { - - private final Duration delay; - - private final O outboundMessage; - - private final Channel channel; - - private final Protocol protocol; - - private final ActionHandler actionHandler; - - AutoValue_ProbingAction( - Duration delay, - O outboundMessage, - Channel channel, - Protocol protocol, - ActionHandler actionHandler) { - if (delay == null) { - throw new NullPointerException("Null delay"); - } - this.delay = delay; - if (outboundMessage == null) { - throw new NullPointerException("Null outboundMessage"); - } - this.outboundMessage = outboundMessage; - if (channel == null) { - throw new NullPointerException("Null channel"); - } - this.channel = channel; - if (protocol == null) { - throw new NullPointerException("Null protocol"); - } - this.protocol = protocol; - if (actionHandler == null) { - throw new NullPointerException("Null actionHandler"); - } - this.actionHandler = actionHandler; - } - - @Override - Duration delay() { - return delay; - } - - @Override - O outboundMessage() { - return outboundMessage; - } - - @Override - Channel channel() { - return channel; - } - - @Override - Protocol protocol() { - return protocol; - } - - @Override - ActionHandler actionHandler() { - return actionHandler; - } - - @Override - public String toString() { - return "ProbingAction{" - + "delay=" + delay + ", " - + "outboundMessage=" + outboundMessage + ", " - + "channel=" + channel + ", " - + "protocol=" + protocol + ", " - + "actionHandler=" + actionHandler - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof ProbingAction) { - ProbingAction that = (ProbingAction) o; - return this.delay.equals(that.delay()) - && this.outboundMessage.equals(that.outboundMessage()) - && this.channel.equals(that.channel()) - && this.protocol.equals(that.protocol()) - && this.actionHandler.equals(that.actionHandler()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= delay.hashCode(); - h$ *= 1000003; - h$ ^= outboundMessage.hashCode(); - h$ *= 1000003; - h$ ^= channel.hashCode(); - h$ *= 1000003; - h$ ^= protocol.hashCode(); - h$ *= 1000003; - h$ ^= actionHandler.hashCode(); - return h$; - } - -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java deleted file mode 100644 index 3247cbdd310..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java +++ /dev/null @@ -1,153 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_Protocol extends Protocol { - - private final String name; - - private final int port; - - private final String host; - - private final ImmutableList> handlerProviders; - - private AutoValue_Protocol( - String name, - int port, - String host, - ImmutableList> handlerProviders) { - this.name = name; - this.port = port; - this.host = host; - this.handlerProviders = handlerProviders; - } - - @Override - String name() { - return name; - } - - @Override - int port() { - return port; - } - - @Override - String host() { - return host; - } - - @Override - ImmutableList> handlerProviders() { - return handlerProviders; - } - - @Override - public String toString() { - return "Protocol{" - + "name=" + name + ", " - + "port=" + port + ", " - + "host=" + host + ", " - + "handlerProviders=" + handlerProviders - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof Protocol) { - Protocol that = (Protocol) o; - return this.name.equals(that.name()) - && this.port == that.port() - && this.host.equals(that.host()) - && this.handlerProviders.equals(that.handlerProviders()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= name.hashCode(); - h$ *= 1000003; - h$ ^= port; - h$ *= 1000003; - h$ ^= host.hashCode(); - h$ *= 1000003; - h$ ^= handlerProviders.hashCode(); - return h$; - } - - static final class Builder extends Protocol.Builder { - private String name; - private Integer port; - private String host; - private ImmutableList> handlerProviders; - Builder() { - } - @Override - Protocol.Builder name(String name) { - if (name == null) { - throw new NullPointerException("Null name"); - } - this.name = name; - return this; - } - @Override - Protocol.Builder port(int port) { - this.port = port; - return this; - } - @Override - Protocol.Builder host(String host) { - if (host == null) { - throw new NullPointerException("Null host"); - } - this.host = host; - return this; - } - @Override - Protocol.Builder handlerProviders(ImmutableList> handlerProviders) { - if (handlerProviders == null) { - throw new NullPointerException("Null handlerProviders"); - } - this.handlerProviders = handlerProviders; - return this; - } - @Override - Protocol build() { - String missing = ""; - if (this.name == null) { - missing += " name"; - } - if (this.port == null) { - missing += " port"; - } - if (this.host == null) { - missing += " host"; - } - if (this.handlerProviders == null) { - missing += " handlerProviders"; - } - if (!missing.isEmpty()) { - throw new IllegalStateException("Missing required properties:" + missing); - } - return new AutoValue_Protocol( - this.name, - this.port, - this.host, - this.handlerProviders); - } - } - -} From 8be8fd92ab7dd964d7f4eeba0e564ae7e9ab2b52 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:28:29 -0400 Subject: [PATCH 008/337] Added gitignore within prober --- .../blackbox/ActionHandler_Factory.java | 25 +++ .../DaggerProberModule_ProberComponent.java | 154 +++++++++++++++++ ...aggerWebWhoisModule_WebWhoisComponent.java | 119 ++++++++++++++ ...berModule_ProvideHttpWhoIsPortFactory.java | 29 ++++ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoIsPortFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 29 ++++ ...odule_ProvidePortToProtocolMapFactory.java | 42 +++++ .../blackbox/ProbingStepWeb_Factory.java | 30 ++++ .../blackbox/ProbingStep_Factory.java | 27 +++ .../blackbox/TestToken_Factory.java | 45 +++++ .../blackbox/TestToken_MembersInjector.java | 30 ++++ .../TokenModule_DomainNameFactory.java | 27 +++ .../TokenModule_ProvideTokenFactory.java | 35 ++++ .../blackbox/Token_MembersInjector.java | 31 ++++ .../Tokens/WebWhoisToken_Factory.java | 25 +++ .../WebWhoisModule_HttpWhoisHostFactory.java | 28 ++++ .../WebWhoisModule_HttpWhoisPathFactory.java | 28 ++++ .../WebWhoisModule_HttpWhoisPortFactory.java | 26 +++ .../WebWhoisModule_HttpsWhoisHostFactory.java | 29 ++++ .../WebWhoisModule_HttpsWhoisPathFactory.java | 29 ++++ .../WebWhoisModule_HttpsWhoisPortFactory.java | 26 +++ ...sModule_ProvideHttpClientCodecFactory.java | 31 ++++ ...le_ProvideHttpObjectAggregatorFactory.java | 31 ++++ ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ++++ ...oisModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ++++++ ...isModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ++++++ ...WhoisModule_ProvideSslProviderFactory.java | 30 ++++ ...viderHttpWhoisHandlerProvidersFactory.java | 58 +++++++ ...iderHttpsWhoisHandlerProvidersFactory.java | 75 +++++++++ .../blackbox/WebWhoisToken_Factory.java | 25 +++ .../handlers/ActionHandler_Factory.java | 25 +++ .../handlers/RedirectHandler_Factory.java | 25 +++ .../SslClientInitializer_Factory.java | 35 ++++ .../handlers/WebWhoIsHandler_Factory.java | 25 +++ .../WebWhoisActionHandler_Factory.java | 25 +++ .../DaggerProberModule_ProberComponent.java | 155 ++++++++++++++++++ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...odule_ProvidePortToProtocolMapFactory.java | 43 +++++ .../TokenModule_DomainNameFactory.java | 27 +++ .../TokenModule_ProvideTokenFactory.java | 35 ++++ ...sModule_ProvideHttpClientCodecFactory.java | 31 ++++ ...le_ProvideHttpObjectAggregatorFactory.java | 31 ++++ ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 54 ++++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 54 ++++++ ...WhoisModule_ProvideSslProviderFactory.java | 30 ++++ ...viderHttpWhoisHandlerProvidersFactory.java | 58 +++++++ ...iderHttpsWhoisHandlerProvidersFactory.java | 75 +++++++++ .../DaggerProberModule_ProberComponent.java | 154 +++++++++++++++++ .../DaggerTestModule_TestComponent.java | 46 ++++++ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...odule_ProvidePortToProtocolMapFactory.java | 42 +++++ .../blackbox/TestHandler_Factory.java | 25 +++ .../TestModule_ProvideHandlersFactory.java | 38 +++++ .../TestProtocol_MembersInjector.java | 36 ++++ .../TokenModule_DomainNameFactory.java | 27 +++ .../TokenModule_ProvideTokenFactory.java | 35 ++++ ...sModule_ProvideHttpClientCodecFactory.java | 31 ++++ ...le_ProvideHttpObjectAggregatorFactory.java | 31 ++++ ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ++++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ++++++ ...WhoisModule_ProvideSslProviderFactory.java | 30 ++++ ...viderHttpWhoisHandlerProvidersFactory.java | 58 +++++++ ...iderHttpsWhoisHandlerProvidersFactory.java | 75 +++++++++ 72 files changed, 3018 insertions(+) create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java new file mode 100644 index 00000000000..8a727c63bbb --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ActionHandler_Factory implements Factory { + private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); + + @Override + public ActionHandler get() { + return new ActionHandler(); + } + + public static ActionHandler_Factory create() { + return INSTANCE; + } + + public static ActionHandler newActionHandler() { + return new ActionHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java new file mode 100644 index 00000000000..39af08b1e60 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java @@ -0,0 +1,154 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { + private final ProberModule proberModule; + + private Provider provideHttpWhoisPortProvider; + + private Provider provideHttpWhoisHostProvider; + + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider provideHttpsWhoisPortProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerProberModule_ProberComponent( + ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { + this.proberModule = proberModuleParam; + initialize(proberModuleParam, webWhoisModuleParam); + } + + public static Builder builder() { + return new Builder(); + } + + public static ProberModule.ProberComponent create() { + return new Builder().build(); + } + + private Set getSetOfProtocol() { + return ImmutableSet.of( + provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); + } + + private WebWhoisToken getWebWhoisToken() { + return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); + } + + @SuppressWarnings("unchecked") + private void initialize( + final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { + this.provideHttpWhoisPortProvider = + ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); + this.provideHttpWhoisHostProvider = + WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + provideHttpWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpWhoisHandlerProvidersProvider)); + this.provideHttpsWhoisPortProvider = + ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + provideHttpsWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public ImmutableMap providePortToProtocolMap() { + return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( + proberModule, getSetOfProtocol()); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); + } + + public static final class Builder { + private ProberModule proberModule; + + private WebWhoisModule webWhoisModule; + + private Builder() {} + + public Builder proberModule(ProberModule proberModule) { + this.proberModule = Preconditions.checkNotNull(proberModule); + return this; + } + + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public ProberModule.ProberComponent build() { + if (proberModule == null) { + this.proberModule = new ProberModule(); + } + if (webWhoisModule == null) { + this.webWhoisModule = new WebWhoisModule(); + } + return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); + } + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java new file mode 100644 index 00000000000..ba272c4730a --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java @@ -0,0 +1,119 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerWebWhoisModule_WebWhoisComponent + implements WebWhoisModule.WebWhoisComponent { + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerWebWhoisModule_WebWhoisComponent() { + + initialize(); + } + + public static Builder builder() { + return new Builder(); + } + + public static WebWhoisModule.WebWhoisComponent create() { + return new Builder().build(); + } + + @SuppressWarnings("unchecked") + private void initialize() { + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + WebWhoisModule_HttpWhoisPortFactory.create(), + WebWhoisModule_HttpWhoisHostFactory.create(), + providerHttpWhoisHandlerProvidersProvider)); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + WebWhoisModule_HttpsWhoisPortFactory.create(), + WebWhoisModule_HttpsWhoisHostFactory.create(), + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public Protocol provideHttpWhoisProtocol() { + return provideHttpWhoisProtocolProvider.get(); + } + + @Override + public Protocol provideHttpsWhoisProtocol() { + return provideHttpsWhoisProtocolProvider.get(); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(); + } + + public static final class Builder { + private Builder() {} + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public WebWhoisModule.WebWhoisComponent build() { + return new DaggerWebWhoisModule_WebWhoisComponent(); + } + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java new file mode 100644 index 00000000000..659d36c8249 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoIsPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoIsPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoIsPort(module); + } + + public static ProberModule_ProvideHttpWhoIsPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoIsPortFactory(module); + } + + public static int proxyProvideHttpWhoIsPort(ProberModule instance) { + return instance.provideHttpWhoIsPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..93f9e4f9f48 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(ProberModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..4d560ae3c94 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisProtocolFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisProtocol(module); + } + + public static ProberModule_ProvideHttpWhoisProtocolFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisProtocolFactory(module); + } + + public static int proxyProvideHttpWhoisProtocol(ProberModule instance) { + return instance.provideHttpWhoisProtocol(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java new file mode 100644 index 00000000000..a49efddd550 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoIsPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoIsPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoIsPort(module); + } + + public static ProberModule_ProvideHttpsWhoIsPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoIsPortFactory(module); + } + + public static int proxyProvideHttpsWhoIsPort(ProberModule instance) { + return instance.provideHttpsWhoIsPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..0aee5faf959 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(ProberModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..faaae10cb72 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisProtocolFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisProtocol(module); + } + + public static ProberModule_ProvideHttpsWhoisProtocolFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisProtocolFactory(module); + } + + public static int proxyProvideHttpsWhoisProtocol(ProberModule instance) { + return instance.provideHttpsWhoisProtocol(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java new file mode 100644 index 00000000000..7ab2e4e9dd9 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java @@ -0,0 +1,42 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableMap; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvidePortToProtocolMapFactory + implements Factory> { + private final ProberModule module; + + private final Provider> protocolSetProvider; + + public ProberModule_ProvidePortToProtocolMapFactory( + ProberModule module, Provider> protocolSetProvider) { + this.module = module; + this.protocolSetProvider = protocolSetProvider; + } + + @Override + public ImmutableMap get() { + return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); + } + + public static ProberModule_ProvidePortToProtocolMapFactory create( + ProberModule module, Provider> protocolSetProvider) { + return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); + } + + public static ImmutableMap proxyProvidePortToProtocolMap( + ProberModule instance, Set protocolSet) { + return Preconditions.checkNotNull( + instance.providePortToProtocolMap(protocolSet), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java new file mode 100644 index 00000000000..a8d428b93c2 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProbingStepWeb_Factory implements Factory { + private final Provider protocolProvider; + + public ProbingStepWeb_Factory(Provider protocolProvider) { + this.protocolProvider = protocolProvider; + } + + @Override + public ProbingStepWeb get() { + return new ProbingStepWeb(protocolProvider.get()); + } + + public static ProbingStepWeb_Factory create(Provider protocolProvider) { + return new ProbingStepWeb_Factory(protocolProvider); + } + + public static ProbingStepWeb newProbingStepWeb(Protocol protocol) { + return new ProbingStepWeb(protocol); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java new file mode 100644 index 00000000000..1e8ba7f6af6 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProbingStep_Factory implements Factory> { + @SuppressWarnings("rawtypes") + private static final ProbingStep_Factory INSTANCE = new ProbingStep_Factory(); + + @Override + public ProbingStep get() { + return new ProbingStep(); + } + + @SuppressWarnings("unchecked") + public static ProbingStep_Factory create() { + return INSTANCE; + } + + public static ProbingStep newProbingStep() { + return new ProbingStep(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java new file mode 100644 index 00000000000..fd4bf43308d --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java @@ -0,0 +1,45 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestToken_Factory implements Factory { + private final Provider actionHandlerProvider; + + private final Provider domainNameProvider; + + private final Provider protocolProvider; + + public TestToken_Factory( + Provider actionHandlerProvider, + Provider domainNameProvider, + Provider protocolProvider) { + this.actionHandlerProvider = actionHandlerProvider; + this.domainNameProvider = domainNameProvider; + this.protocolProvider = protocolProvider; + } + + @Override + public TestToken get() { + TestToken instance = new TestToken(actionHandlerProvider.get(), domainNameProvider.get()); + TestToken_MembersInjector.injectProtocol(instance, protocolProvider.get()); + return instance; + } + + public static TestToken_Factory create( + Provider actionHandlerProvider, + Provider domainNameProvider, + Provider protocolProvider) { + return new TestToken_Factory(actionHandlerProvider, domainNameProvider, protocolProvider); + } + + public static TestToken newTestToken(ActionHandler actionHandler, String domainName) { + return new TestToken(actionHandler, domainName); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java new file mode 100644 index 00000000000..db846ba4a36 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.MembersInjector; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestToken_MembersInjector implements MembersInjector { + private final Provider protocolProvider; + + public TestToken_MembersInjector(Provider protocolProvider) { + this.protocolProvider = protocolProvider; + } + + public static MembersInjector create(Provider protocolProvider) { + return new TestToken_MembersInjector(protocolProvider); + } + + @Override + public void injectMembers(TestToken instance) { + injectProtocol(instance, protocolProvider.get()); + } + + public static void injectProtocol(TestToken instance, Protocol protocol) { + instance.protocol = protocol; + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java new file mode 100644 index 00000000000..1dc41bf0e16 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_DomainNameFactory implements Factory { + private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); + + @Override + public String get() { + return proxyDomainName(); + } + + public static TokenModule_DomainNameFactory create() { + return INSTANCE; + } + + public static String proxyDomainName() { + return Preconditions.checkNotNull( + TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java new file mode 100644 index 00000000000..afc66775c9d --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_ProvideTokenFactory implements Factory { + private final Provider tokenProvider; + + public TokenModule_ProvideTokenFactory(Provider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public Token get() { + return proxyProvideToken(tokenProvider.get()); + } + + public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { + return new TokenModule_ProvideTokenFactory(tokenProvider); + } + + public static Token proxyProvideToken(WebWhoisToken token) { + return Preconditions.checkNotNull( + TokenModule.provideToken(token), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java new file mode 100644 index 00000000000..feab7f7d227 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.MembersInjector; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class Token_MembersInjector implements MembersInjector { + private final Provider actionHandlerProvider; + + public Token_MembersInjector(Provider actionHandlerProvider) { + this.actionHandlerProvider = actionHandlerProvider; + } + + public static MembersInjector create(Provider actionHandlerProvider) { + return new Token_MembersInjector(actionHandlerProvider); + } + + @Override + public void injectMembers(Token instance) { + injectActionHandler(instance, actionHandlerProvider.get()); + } + + public static void injectActionHandler(Object instance, ActionHandler actionHandler) { + ((Token) instance).actionHandler = actionHandler; + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java new file mode 100644 index 00000000000..3d153c08fdb --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.Tokens; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisToken_Factory implements Factory { + private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); + + @Override + public WebWhoisToken get() { + return new WebWhoisToken(); + } + + public static WebWhoisToken_Factory create() { + return INSTANCE; + } + + public static WebWhoisToken newWebWhoisToken() { + return new WebWhoisToken(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java new file mode 100644 index 00000000000..f2f34a674d3 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java @@ -0,0 +1,28 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpWhoisHostFactory implements Factory { + private static final WebWhoisModule_HttpWhoisHostFactory INSTANCE = + new WebWhoisModule_HttpWhoisHostFactory(); + + @Override + public String get() { + return proxyHttpWhoisHost(); + } + + public static WebWhoisModule_HttpWhoisHostFactory create() { + return INSTANCE; + } + + public static String proxyHttpWhoisHost() { + return Preconditions.checkNotNull( + WebWhoisModule.httpWhoisHost(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java new file mode 100644 index 00000000000..67ab24c06fd --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java @@ -0,0 +1,28 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpWhoisPathFactory implements Factory { + private static final WebWhoisModule_HttpWhoisPathFactory INSTANCE = + new WebWhoisModule_HttpWhoisPathFactory(); + + @Override + public String get() { + return proxyHttpWhoisPath(); + } + + public static WebWhoisModule_HttpWhoisPathFactory create() { + return INSTANCE; + } + + public static String proxyHttpWhoisPath() { + return Preconditions.checkNotNull( + WebWhoisModule.httpWhoisPath(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java new file mode 100644 index 00000000000..4a29a990b67 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java @@ -0,0 +1,26 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpWhoisPortFactory implements Factory { + private static final WebWhoisModule_HttpWhoisPortFactory INSTANCE = + new WebWhoisModule_HttpWhoisPortFactory(); + + @Override + public Integer get() { + return proxyHttpWhoisPort(); + } + + public static WebWhoisModule_HttpWhoisPortFactory create() { + return INSTANCE; + } + + public static int proxyHttpWhoisPort() { + return WebWhoisModule.httpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java new file mode 100644 index 00000000000..f8a7fae07a8 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpsWhoisHostFactory implements Factory { + private static final WebWhoisModule_HttpsWhoisHostFactory INSTANCE = + new WebWhoisModule_HttpsWhoisHostFactory(); + + @Override + public String get() { + return proxyHttpsWhoisHost(); + } + + public static WebWhoisModule_HttpsWhoisHostFactory create() { + return INSTANCE; + } + + public static String proxyHttpsWhoisHost() { + return Preconditions.checkNotNull( + WebWhoisModule.httpsWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java new file mode 100644 index 00000000000..4cabb7b5384 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpsWhoisPathFactory implements Factory { + private static final WebWhoisModule_HttpsWhoisPathFactory INSTANCE = + new WebWhoisModule_HttpsWhoisPathFactory(); + + @Override + public String get() { + return proxyHttpsWhoisPath(); + } + + public static WebWhoisModule_HttpsWhoisPathFactory create() { + return INSTANCE; + } + + public static String proxyHttpsWhoisPath() { + return Preconditions.checkNotNull( + WebWhoisModule.httpsWhoisPath(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java new file mode 100644 index 00000000000..30f4564213a --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java @@ -0,0 +1,26 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpsWhoisPortFactory implements Factory { + private static final WebWhoisModule_HttpsWhoisPortFactory INSTANCE = + new WebWhoisModule_HttpsWhoisPortFactory(); + + @Override + public Integer get() { + return proxyHttpsWhoisPort(); + } + + public static WebWhoisModule_HttpsWhoisPortFactory create() { + return INSTANCE; + } + + public static int proxyHttpsWhoisPort() { + return WebWhoisModule.httpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java new file mode 100644 index 00000000000..7c756174314 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpClientCodec; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpClientCodecFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = + new WebWhoisModule_ProvideHttpClientCodecFactory(); + + @Override + public HttpClientCodec get() { + return proxyProvideHttpClientCodec(); + } + + public static WebWhoisModule_ProvideHttpClientCodecFactory create() { + return INSTANCE; + } + + public static HttpClientCodec proxyProvideHttpClientCodec() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpClientCodec(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java new file mode 100644 index 00000000000..20785cde372 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = + new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); + + @Override + public HttpObjectAggregator get() { + return proxyProvideHttpObjectAggregator(); + } + + public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { + return INSTANCE; + } + + public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpObjectAggregator(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java new file mode 100644 index 00000000000..7087ab940bc --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java @@ -0,0 +1,32 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public String get() { + return proxyProvideHttpWhoisHost(module); + } + + public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); + } + + public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { + return Preconditions.checkNotNull( + instance.provideHttpWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..a4aaf24978e --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisPortFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisPortFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static WebWhoisModule_ProvideHttpWhoisPortFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(WebWhoisModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..ed7e62f3a5f --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final Provider httpWhoisPortProvider; + + private final Provider httpWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpWhoisProtocolFactory( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpWhoisPortProvider = httpWhoisPortProvider; + this.httpWhoisHostProvider = httpWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpWhoisProtocol( + httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( + httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpWhoisProtocol( + int httpWhoisPort, + String httpWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..c3d7c6546e5 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisPortFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpsWhoisPortFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static WebWhoisModule_ProvideHttpsWhoisPortFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(WebWhoisModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..4ab50681eea --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final Provider httpsWhoisPortProvider; + + private final Provider httpsWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpsWhoisPortProvider = httpsWhoisPortProvider; + this.httpsWhoisHostProvider = httpsWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpsWhoisProtocol( + httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpsWhoisProtocol( + int httpsWhoisPort, + String httpsWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java new file mode 100644 index 00000000000..7579cc752cf --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { + private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = + new WebWhoisModule_ProvideSslProviderFactory(); + + @Override + public SslProvider get() { + return proxyProvideSslProvider(); + } + + public static WebWhoisModule_ProvideSslProviderFactory create() { + return INSTANCE; + } + + public static SslProvider proxyProvideSslProvider() { + return Preconditions.checkNotNull( + WebWhoisModule.provideSslProvider(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..37431babcb9 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java @@ -0,0 +1,58 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpWhoisHandlerProviders( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..adf393894e8 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java @@ -0,0 +1,75 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider> sslClientInitializerProvider; + + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.sslClientInitializerProvider = sslClientInitializerProvider; + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpsWhoisHandlerProviders( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java new file mode 100644 index 00000000000..6c840214a11 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisToken_Factory implements Factory { + private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); + + @Override + public WebWhoisToken get() { + return new WebWhoisToken(); + } + + public static WebWhoisToken_Factory create() { + return INSTANCE; + } + + public static WebWhoisToken newWebWhoisToken() { + return new WebWhoisToken(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java new file mode 100644 index 00000000000..d94df8b392f --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ActionHandler_Factory implements Factory { + private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); + + @Override + public ActionHandler get() { + return new ActionHandler(); + } + + public static ActionHandler_Factory create() { + return INSTANCE; + } + + public static ActionHandler newActionHandler() { + return new ActionHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java new file mode 100644 index 00000000000..ddf10cf830b --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class RedirectHandler_Factory implements Factory { + private static final RedirectHandler_Factory INSTANCE = new RedirectHandler_Factory(); + + @Override + public RedirectHandler get() { + return new RedirectHandler(); + } + + public static RedirectHandler_Factory create() { + return INSTANCE; + } + + public static RedirectHandler newRedirectHandler() { + return new RedirectHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java new file mode 100644 index 00000000000..7fa480f418e --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import io.netty.channel.Channel; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class SslClientInitializer_Factory + implements Factory> { + private final Provider sslProvider; + + public SslClientInitializer_Factory(Provider sslProvider) { + this.sslProvider = sslProvider; + } + + @Override + public SslClientInitializer get() { + return new SslClientInitializer(sslProvider.get()); + } + + public static SslClientInitializer_Factory create( + Provider sslProvider) { + return new SslClientInitializer_Factory(sslProvider); + } + + public static SslClientInitializer newSslClientInitializer( + SslProvider sslProvider) { + return new SslClientInitializer(sslProvider); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java new file mode 100644 index 00000000000..26b68fdc09c --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoIsHandler_Factory implements Factory { + private static final WebWhoIsHandler_Factory INSTANCE = new WebWhoIsHandler_Factory(); + + @Override + public WebWhoIsHandler get() { + return new WebWhoIsHandler(); + } + + public static WebWhoIsHandler_Factory create() { + return INSTANCE; + } + + public static WebWhoIsHandler newWebWhoIsHandler() { + return new WebWhoIsHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java new file mode 100644 index 00000000000..dc008e1a724 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisActionHandler_Factory implements Factory { + private static final WebWhoisActionHandler_Factory INSTANCE = new WebWhoisActionHandler_Factory(); + + @Override + public WebWhoisActionHandler get() { + return new WebWhoisActionHandler(); + } + + public static WebWhoisActionHandler_Factory create() { + return INSTANCE; + } + + public static WebWhoisActionHandler newWebWhoisActionHandler() { + return new WebWhoisActionHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java new file mode 100644 index 00000000000..b7971395941 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java @@ -0,0 +1,155 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { + private final ProberModule proberModule; + + private Provider provideHttpWhoisPortProvider; + + private Provider provideHttpWhoisHostProvider; + + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider provideHttpsWhoisPortProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerProberModule_ProberComponent( + ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { + this.proberModule = proberModuleParam; + initialize(proberModuleParam, webWhoisModuleParam); + } + + public static Builder builder() { + return new Builder(); + } + + public static ProberModule.ProberComponent create() { + return new Builder().build(); + } + + private Set getSetOfProtocol() { + return ImmutableSet.of( + provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); + } + + private WebWhoisToken getWebWhoisToken() { + return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); + } + + @SuppressWarnings("unchecked") + private void initialize( + final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { + this.provideHttpWhoisPortProvider = + ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); + this.provideHttpWhoisHostProvider = + WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + provideHttpWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpWhoisHandlerProvidersProvider)); + this.provideHttpsWhoisPortProvider = + ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + provideHttpsWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public ImmutableMap providePortToProtocolMap() { + return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( + proberModule, getSetOfProtocol()); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); + } + + public static final class Builder { + private ProberModule proberModule; + + private WebWhoisModule webWhoisModule; + + private Builder() {} + + public Builder proberModule(ProberModule proberModule) { + this.proberModule = Preconditions.checkNotNull(proberModule); + return this; + } + + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public ProberModule.ProberComponent build() { + if (proberModule == null) { + this.proberModule = new ProberModule(); + } + if (webWhoisModule == null) { + this.webWhoisModule = new WebWhoisModule(); + } + return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); + } + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..955698498db --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(ProberModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..0b97c8dbb72 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(ProberModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java new file mode 100644 index 00000000000..e0597aa25f5 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java @@ -0,0 +1,43 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableMap; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvidePortToProtocolMapFactory + implements Factory> { + private final ProberModule module; + + private final Provider> protocolSetProvider; + + public ProberModule_ProvidePortToProtocolMapFactory( + ProberModule module, Provider> protocolSetProvider) { + this.module = module; + this.protocolSetProvider = protocolSetProvider; + } + + @Override + public ImmutableMap get() { + return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); + } + + public static ProberModule_ProvidePortToProtocolMapFactory create( + ProberModule module, Provider> protocolSetProvider) { + return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); + } + + public static ImmutableMap proxyProvidePortToProtocolMap( + ProberModule instance, Set protocolSet) { + return Preconditions.checkNotNull( + instance.providePortToProtocolMap(protocolSet), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java new file mode 100644 index 00000000000..20e2ca11502 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_DomainNameFactory implements Factory { + private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); + + @Override + public String get() { + return proxyDomainName(); + } + + public static TokenModule_DomainNameFactory create() { + return INSTANCE; + } + + public static String proxyDomainName() { + return Preconditions.checkNotNull( + TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java new file mode 100644 index 00000000000..e6628332802 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_ProvideTokenFactory implements Factory { + private final Provider tokenProvider; + + public TokenModule_ProvideTokenFactory(Provider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public Token get() { + return proxyProvideToken(tokenProvider.get()); + } + + public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { + return new TokenModule_ProvideTokenFactory(tokenProvider); + } + + public static Token proxyProvideToken(WebWhoisToken token) { + return Preconditions.checkNotNull( + TokenModule.provideToken(token), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java new file mode 100644 index 00000000000..31710bed6eb --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpClientCodec; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpClientCodecFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = + new WebWhoisModule_ProvideHttpClientCodecFactory(); + + @Override + public HttpClientCodec get() { + return proxyProvideHttpClientCodec(); + } + + public static WebWhoisModule_ProvideHttpClientCodecFactory create() { + return INSTANCE; + } + + public static HttpClientCodec proxyProvideHttpClientCodec() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpClientCodec(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java new file mode 100644 index 00000000000..b69df1a2f7d --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = + new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); + + @Override + public HttpObjectAggregator get() { + return proxyProvideHttpObjectAggregator(); + } + + public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { + return INSTANCE; + } + + public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpObjectAggregator(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java new file mode 100644 index 00000000000..bacebd82f49 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java @@ -0,0 +1,32 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public String get() { + return proxyProvideHttpWhoisHost(module); + } + + public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); + } + + public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { + return Preconditions.checkNotNull( + instance.provideHttpWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..0d098288569 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,54 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final Provider httpWhoisPortProvider; + + private final Provider httpWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpWhoisProtocolFactory( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpWhoisPortProvider = httpWhoisPortProvider; + this.httpWhoisHostProvider = httpWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpWhoisProtocol( + httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( + httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpWhoisProtocol( + int httpWhoisPort, + String httpWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..c40cde16709 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,54 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final Provider httpsWhoisPortProvider; + + private final Provider httpsWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpsWhoisPortProvider = httpsWhoisPortProvider; + this.httpsWhoisHostProvider = httpsWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpsWhoisProtocol( + httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpsWhoisProtocol( + int httpsWhoisPort, + String httpsWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java new file mode 100644 index 00000000000..208d9c7212e --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { + private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = + new WebWhoisModule_ProvideSslProviderFactory(); + + @Override + public SslProvider get() { + return proxyProvideSslProvider(); + } + + public static WebWhoisModule_ProvideSslProviderFactory create() { + return INSTANCE; + } + + public static SslProvider proxyProvideSslProvider() { + return Preconditions.checkNotNull( + WebWhoisModule.provideSslProvider(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..81eb6efc487 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java @@ -0,0 +1,58 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpWhoisHandlerProviders( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..e18a43dd7a8 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java @@ -0,0 +1,75 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider> sslClientInitializerProvider; + + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.sslClientInitializerProvider = sslClientInitializerProvider; + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpsWhoisHandlerProviders( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java new file mode 100644 index 00000000000..39af08b1e60 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java @@ -0,0 +1,154 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { + private final ProberModule proberModule; + + private Provider provideHttpWhoisPortProvider; + + private Provider provideHttpWhoisHostProvider; + + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider provideHttpsWhoisPortProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerProberModule_ProberComponent( + ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { + this.proberModule = proberModuleParam; + initialize(proberModuleParam, webWhoisModuleParam); + } + + public static Builder builder() { + return new Builder(); + } + + public static ProberModule.ProberComponent create() { + return new Builder().build(); + } + + private Set getSetOfProtocol() { + return ImmutableSet.of( + provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); + } + + private WebWhoisToken getWebWhoisToken() { + return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); + } + + @SuppressWarnings("unchecked") + private void initialize( + final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { + this.provideHttpWhoisPortProvider = + ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); + this.provideHttpWhoisHostProvider = + WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + provideHttpWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpWhoisHandlerProvidersProvider)); + this.provideHttpsWhoisPortProvider = + ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + provideHttpsWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public ImmutableMap providePortToProtocolMap() { + return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( + proberModule, getSetOfProtocol()); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); + } + + public static final class Builder { + private ProberModule proberModule; + + private WebWhoisModule webWhoisModule; + + private Builder() {} + + public Builder proberModule(ProberModule proberModule) { + this.proberModule = Preconditions.checkNotNull(proberModule); + return this; + } + + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public ProberModule.ProberComponent build() { + if (proberModule == null) { + this.proberModule = new ProberModule(); + } + if (webWhoisModule == null) { + this.webWhoisModule = new WebWhoisModule(); + } + return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); + } + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java new file mode 100644 index 00000000000..45032a9c7ba --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java @@ -0,0 +1,46 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerTestModule_TestComponent implements TestModule.TestComponent { + private DaggerTestModule_TestComponent() {} + + public static Builder builder() { + return new Builder(); + } + + public static TestModule.TestComponent create() { + return new Builder().build(); + } + + @Override + public ImmutableList> provideHandlers() { + return TestModule_ProvideHandlersFactory.proxyProvideHandlers(TestHandler_Factory.create()); + } + + public static final class Builder { + private Builder() {} + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder testModule(TestModule testModule) { + Preconditions.checkNotNull(testModule); + return this; + } + + public TestModule.TestComponent build() { + return new DaggerTestModule_TestComponent(); + } + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..93f9e4f9f48 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(ProberModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..0aee5faf959 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(ProberModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java new file mode 100644 index 00000000000..7ab2e4e9dd9 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java @@ -0,0 +1,42 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableMap; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvidePortToProtocolMapFactory + implements Factory> { + private final ProberModule module; + + private final Provider> protocolSetProvider; + + public ProberModule_ProvidePortToProtocolMapFactory( + ProberModule module, Provider> protocolSetProvider) { + this.module = module; + this.protocolSetProvider = protocolSetProvider; + } + + @Override + public ImmutableMap get() { + return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); + } + + public static ProberModule_ProvidePortToProtocolMapFactory create( + ProberModule module, Provider> protocolSetProvider) { + return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); + } + + public static ImmutableMap proxyProvidePortToProtocolMap( + ProberModule instance, Set protocolSet) { + return Preconditions.checkNotNull( + instance.providePortToProtocolMap(protocolSet), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java new file mode 100644 index 00000000000..50616d20699 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestHandler_Factory implements Factory { + private static final TestHandler_Factory INSTANCE = new TestHandler_Factory(); + + @Override + public TestHandler get() { + return new TestHandler(); + } + + public static TestHandler_Factory create() { + return INSTANCE; + } + + public static TestHandler newTestHandler() { + return new TestHandler(); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java new file mode 100644 index 00000000000..79e40ee2d4a --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java @@ -0,0 +1,38 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestModule_ProvideHandlersFactory + implements Factory>> { + private final Provider testHandlerProvider; + + public TestModule_ProvideHandlersFactory(Provider testHandlerProvider) { + this.testHandlerProvider = testHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProvideHandlers(testHandlerProvider); + } + + public static TestModule_ProvideHandlersFactory create( + Provider testHandlerProvider) { + return new TestModule_ProvideHandlersFactory(testHandlerProvider); + } + + public static ImmutableList> proxyProvideHandlers( + Provider testHandlerProvider) { + return Preconditions.checkNotNull( + TestModule.provideHandlers(testHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java new file mode 100644 index 00000000000..75b788ec968 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java @@ -0,0 +1,36 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.MembersInjector; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestProtocol_MembersInjector implements MembersInjector { + private final Provider>> + handlerProvidersProvider; + + public TestProtocol_MembersInjector( + Provider>> handlerProvidersProvider) { + this.handlerProvidersProvider = handlerProvidersProvider; + } + + public static MembersInjector create( + Provider>> handlerProvidersProvider) { + return new TestProtocol_MembersInjector(handlerProvidersProvider); + } + + @Override + public void injectMembers(TestProtocol instance) { + injectTestProtocolHandlers(instance, handlerProvidersProvider.get()); + } + + public static void injectTestProtocolHandlers( + TestProtocol instance, ImmutableList> handlerProviders) { + instance.TestProtocolHandlers(handlerProviders); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java new file mode 100644 index 00000000000..1dc41bf0e16 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_DomainNameFactory implements Factory { + private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); + + @Override + public String get() { + return proxyDomainName(); + } + + public static TokenModule_DomainNameFactory create() { + return INSTANCE; + } + + public static String proxyDomainName() { + return Preconditions.checkNotNull( + TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java new file mode 100644 index 00000000000..afc66775c9d --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_ProvideTokenFactory implements Factory { + private final Provider tokenProvider; + + public TokenModule_ProvideTokenFactory(Provider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public Token get() { + return proxyProvideToken(tokenProvider.get()); + } + + public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { + return new TokenModule_ProvideTokenFactory(tokenProvider); + } + + public static Token proxyProvideToken(WebWhoisToken token) { + return Preconditions.checkNotNull( + TokenModule.provideToken(token), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java new file mode 100644 index 00000000000..7c756174314 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpClientCodec; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpClientCodecFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = + new WebWhoisModule_ProvideHttpClientCodecFactory(); + + @Override + public HttpClientCodec get() { + return proxyProvideHttpClientCodec(); + } + + public static WebWhoisModule_ProvideHttpClientCodecFactory create() { + return INSTANCE; + } + + public static HttpClientCodec proxyProvideHttpClientCodec() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpClientCodec(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java new file mode 100644 index 00000000000..20785cde372 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = + new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); + + @Override + public HttpObjectAggregator get() { + return proxyProvideHttpObjectAggregator(); + } + + public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { + return INSTANCE; + } + + public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpObjectAggregator(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java new file mode 100644 index 00000000000..7087ab940bc --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java @@ -0,0 +1,32 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public String get() { + return proxyProvideHttpWhoisHost(module); + } + + public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); + } + + public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { + return Preconditions.checkNotNull( + instance.provideHttpWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..ed7e62f3a5f --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final Provider httpWhoisPortProvider; + + private final Provider httpWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpWhoisProtocolFactory( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpWhoisPortProvider = httpWhoisPortProvider; + this.httpWhoisHostProvider = httpWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpWhoisProtocol( + httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( + httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpWhoisProtocol( + int httpWhoisPort, + String httpWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..4ab50681eea --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final Provider httpsWhoisPortProvider; + + private final Provider httpsWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpsWhoisPortProvider = httpsWhoisPortProvider; + this.httpsWhoisHostProvider = httpsWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpsWhoisProtocol( + httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpsWhoisProtocol( + int httpsWhoisPort, + String httpsWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java new file mode 100644 index 00000000000..7579cc752cf --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { + private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = + new WebWhoisModule_ProvideSslProviderFactory(); + + @Override + public SslProvider get() { + return proxyProvideSslProvider(); + } + + public static WebWhoisModule_ProvideSslProviderFactory create() { + return INSTANCE; + } + + public static SslProvider proxyProvideSslProvider() { + return Preconditions.checkNotNull( + WebWhoisModule.provideSslProvider(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..37431babcb9 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java @@ -0,0 +1,58 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpWhoisHandlerProviders( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..adf393894e8 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java @@ -0,0 +1,75 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider> sslClientInitializerProvider; + + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.sslClientInitializerProvider = sslClientInitializerProvider; + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpsWhoisHandlerProviders( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} From e0e3d82947e69d91bc91de158de462098918e572 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:29:25 -0400 Subject: [PATCH 009/337] Removed all generated java --- .../blackbox/ActionHandler_Factory.java | 25 --- .../DaggerProberModule_ProberComponent.java | 154 ----------------- ...aggerWebWhoisModule_WebWhoisComponent.java | 119 -------------- ...berModule_ProvideHttpWhoIsPortFactory.java | 29 ---- ...berModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 29 ---- ...erModule_ProvideHttpsWhoIsPortFactory.java | 29 ---- ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...dule_ProvideHttpsWhoisProtocolFactory.java | 29 ---- ...odule_ProvidePortToProtocolMapFactory.java | 42 ----- .../blackbox/ProbingStepWeb_Factory.java | 30 ---- .../blackbox/ProbingStep_Factory.java | 27 --- .../blackbox/TestToken_Factory.java | 45 ----- .../blackbox/TestToken_MembersInjector.java | 30 ---- .../TokenModule_DomainNameFactory.java | 27 --- .../TokenModule_ProvideTokenFactory.java | 35 ---- .../blackbox/Token_MembersInjector.java | 31 ---- .../Tokens/WebWhoisToken_Factory.java | 25 --- .../WebWhoisModule_HttpWhoisHostFactory.java | 28 ---- .../WebWhoisModule_HttpWhoisPathFactory.java | 28 ---- .../WebWhoisModule_HttpWhoisPortFactory.java | 26 --- .../WebWhoisModule_HttpsWhoisHostFactory.java | 29 ---- .../WebWhoisModule_HttpsWhoisPathFactory.java | 29 ---- .../WebWhoisModule_HttpsWhoisPortFactory.java | 26 --- ...sModule_ProvideHttpClientCodecFactory.java | 31 ---- ...le_ProvideHttpObjectAggregatorFactory.java | 31 ---- ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ---- ...oisModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ------ ...isModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ------ ...WhoisModule_ProvideSslProviderFactory.java | 30 ---- ...viderHttpWhoisHandlerProvidersFactory.java | 58 ------- ...iderHttpsWhoisHandlerProvidersFactory.java | 75 --------- .../blackbox/WebWhoisToken_Factory.java | 25 --- .../handlers/ActionHandler_Factory.java | 25 --- .../handlers/RedirectHandler_Factory.java | 25 --- .../SslClientInitializer_Factory.java | 35 ---- .../handlers/WebWhoIsHandler_Factory.java | 25 --- .../WebWhoisActionHandler_Factory.java | 25 --- .../DaggerProberModule_ProberComponent.java | 155 ------------------ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...odule_ProvidePortToProtocolMapFactory.java | 43 ----- .../TokenModule_DomainNameFactory.java | 27 --- .../TokenModule_ProvideTokenFactory.java | 35 ---- ...sModule_ProvideHttpClientCodecFactory.java | 31 ---- ...le_ProvideHttpObjectAggregatorFactory.java | 31 ---- ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 54 ------ ...dule_ProvideHttpsWhoisProtocolFactory.java | 54 ------ ...WhoisModule_ProvideSslProviderFactory.java | 30 ---- ...viderHttpWhoisHandlerProvidersFactory.java | 58 ------- ...iderHttpsWhoisHandlerProvidersFactory.java | 75 --------- .../DaggerProberModule_ProberComponent.java | 154 ----------------- .../DaggerTestModule_TestComponent.java | 46 ------ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...odule_ProvidePortToProtocolMapFactory.java | 42 ----- .../blackbox/TestHandler_Factory.java | 25 --- .../TestModule_ProvideHandlersFactory.java | 38 ----- .../TestProtocol_MembersInjector.java | 36 ---- .../TokenModule_DomainNameFactory.java | 27 --- .../TokenModule_ProvideTokenFactory.java | 35 ---- ...sModule_ProvideHttpClientCodecFactory.java | 31 ---- ...le_ProvideHttpObjectAggregatorFactory.java | 31 ---- ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ------ ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ------ ...WhoisModule_ProvideSslProviderFactory.java | 30 ---- ...viderHttpWhoisHandlerProvidersFactory.java | 58 ------- ...iderHttpsWhoisHandlerProvidersFactory.java | 75 --------- 72 files changed, 3018 deletions(-) delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java deleted file mode 100644 index 8a727c63bbb..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ActionHandler_Factory implements Factory { - private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); - - @Override - public ActionHandler get() { - return new ActionHandler(); - } - - public static ActionHandler_Factory create() { - return INSTANCE; - } - - public static ActionHandler newActionHandler() { - return new ActionHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java deleted file mode 100644 index 39af08b1e60..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java +++ /dev/null @@ -1,154 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { - private final ProberModule proberModule; - - private Provider provideHttpWhoisPortProvider; - - private Provider provideHttpWhoisHostProvider; - - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider provideHttpsWhoisPortProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerProberModule_ProberComponent( - ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { - this.proberModule = proberModuleParam; - initialize(proberModuleParam, webWhoisModuleParam); - } - - public static Builder builder() { - return new Builder(); - } - - public static ProberModule.ProberComponent create() { - return new Builder().build(); - } - - private Set getSetOfProtocol() { - return ImmutableSet.of( - provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); - } - - private WebWhoisToken getWebWhoisToken() { - return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); - } - - @SuppressWarnings("unchecked") - private void initialize( - final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { - this.provideHttpWhoisPortProvider = - ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); - this.provideHttpWhoisHostProvider = - WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - provideHttpWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpWhoisHandlerProvidersProvider)); - this.provideHttpsWhoisPortProvider = - ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - provideHttpsWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public ImmutableMap providePortToProtocolMap() { - return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( - proberModule, getSetOfProtocol()); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); - } - - public static final class Builder { - private ProberModule proberModule; - - private WebWhoisModule webWhoisModule; - - private Builder() {} - - public Builder proberModule(ProberModule proberModule) { - this.proberModule = Preconditions.checkNotNull(proberModule); - return this; - } - - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public ProberModule.ProberComponent build() { - if (proberModule == null) { - this.proberModule = new ProberModule(); - } - if (webWhoisModule == null) { - this.webWhoisModule = new WebWhoisModule(); - } - return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); - } - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java deleted file mode 100644 index ba272c4730a..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java +++ /dev/null @@ -1,119 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerWebWhoisModule_WebWhoisComponent - implements WebWhoisModule.WebWhoisComponent { - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerWebWhoisModule_WebWhoisComponent() { - - initialize(); - } - - public static Builder builder() { - return new Builder(); - } - - public static WebWhoisModule.WebWhoisComponent create() { - return new Builder().build(); - } - - @SuppressWarnings("unchecked") - private void initialize() { - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - WebWhoisModule_HttpWhoisPortFactory.create(), - WebWhoisModule_HttpWhoisHostFactory.create(), - providerHttpWhoisHandlerProvidersProvider)); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - WebWhoisModule_HttpsWhoisPortFactory.create(), - WebWhoisModule_HttpsWhoisHostFactory.create(), - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public Protocol provideHttpWhoisProtocol() { - return provideHttpWhoisProtocolProvider.get(); - } - - @Override - public Protocol provideHttpsWhoisProtocol() { - return provideHttpsWhoisProtocolProvider.get(); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(); - } - - public static final class Builder { - private Builder() {} - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public WebWhoisModule.WebWhoisComponent build() { - return new DaggerWebWhoisModule_WebWhoisComponent(); - } - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java deleted file mode 100644 index 659d36c8249..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoIsPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoIsPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoIsPort(module); - } - - public static ProberModule_ProvideHttpWhoIsPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoIsPortFactory(module); - } - - public static int proxyProvideHttpWhoIsPort(ProberModule instance) { - return instance.provideHttpWhoIsPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index 93f9e4f9f48..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(ProberModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index 4d560ae3c94..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisProtocolFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisProtocol(module); - } - - public static ProberModule_ProvideHttpWhoisProtocolFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisProtocolFactory(module); - } - - public static int proxyProvideHttpWhoisProtocol(ProberModule instance) { - return instance.provideHttpWhoisProtocol(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java deleted file mode 100644 index a49efddd550..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoIsPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoIsPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoIsPort(module); - } - - public static ProberModule_ProvideHttpsWhoIsPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoIsPortFactory(module); - } - - public static int proxyProvideHttpsWhoIsPort(ProberModule instance) { - return instance.provideHttpsWhoIsPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index 0aee5faf959..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(ProberModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index faaae10cb72..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisProtocolFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisProtocol(module); - } - - public static ProberModule_ProvideHttpsWhoisProtocolFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisProtocolFactory(module); - } - - public static int proxyProvideHttpsWhoisProtocol(ProberModule instance) { - return instance.provideHttpsWhoisProtocol(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java deleted file mode 100644 index 7ab2e4e9dd9..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableMap; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvidePortToProtocolMapFactory - implements Factory> { - private final ProberModule module; - - private final Provider> protocolSetProvider; - - public ProberModule_ProvidePortToProtocolMapFactory( - ProberModule module, Provider> protocolSetProvider) { - this.module = module; - this.protocolSetProvider = protocolSetProvider; - } - - @Override - public ImmutableMap get() { - return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); - } - - public static ProberModule_ProvidePortToProtocolMapFactory create( - ProberModule module, Provider> protocolSetProvider) { - return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); - } - - public static ImmutableMap proxyProvidePortToProtocolMap( - ProberModule instance, Set protocolSet) { - return Preconditions.checkNotNull( - instance.providePortToProtocolMap(protocolSet), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java deleted file mode 100644 index a8d428b93c2..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProbingStepWeb_Factory implements Factory { - private final Provider protocolProvider; - - public ProbingStepWeb_Factory(Provider protocolProvider) { - this.protocolProvider = protocolProvider; - } - - @Override - public ProbingStepWeb get() { - return new ProbingStepWeb(protocolProvider.get()); - } - - public static ProbingStepWeb_Factory create(Provider protocolProvider) { - return new ProbingStepWeb_Factory(protocolProvider); - } - - public static ProbingStepWeb newProbingStepWeb(Protocol protocol) { - return new ProbingStepWeb(protocol); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java deleted file mode 100644 index 1e8ba7f6af6..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProbingStep_Factory implements Factory> { - @SuppressWarnings("rawtypes") - private static final ProbingStep_Factory INSTANCE = new ProbingStep_Factory(); - - @Override - public ProbingStep get() { - return new ProbingStep(); - } - - @SuppressWarnings("unchecked") - public static ProbingStep_Factory create() { - return INSTANCE; - } - - public static ProbingStep newProbingStep() { - return new ProbingStep(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java deleted file mode 100644 index fd4bf43308d..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java +++ /dev/null @@ -1,45 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestToken_Factory implements Factory { - private final Provider actionHandlerProvider; - - private final Provider domainNameProvider; - - private final Provider protocolProvider; - - public TestToken_Factory( - Provider actionHandlerProvider, - Provider domainNameProvider, - Provider protocolProvider) { - this.actionHandlerProvider = actionHandlerProvider; - this.domainNameProvider = domainNameProvider; - this.protocolProvider = protocolProvider; - } - - @Override - public TestToken get() { - TestToken instance = new TestToken(actionHandlerProvider.get(), domainNameProvider.get()); - TestToken_MembersInjector.injectProtocol(instance, protocolProvider.get()); - return instance; - } - - public static TestToken_Factory create( - Provider actionHandlerProvider, - Provider domainNameProvider, - Provider protocolProvider) { - return new TestToken_Factory(actionHandlerProvider, domainNameProvider, protocolProvider); - } - - public static TestToken newTestToken(ActionHandler actionHandler, String domainName) { - return new TestToken(actionHandler, domainName); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java deleted file mode 100644 index db846ba4a36..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.MembersInjector; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestToken_MembersInjector implements MembersInjector { - private final Provider protocolProvider; - - public TestToken_MembersInjector(Provider protocolProvider) { - this.protocolProvider = protocolProvider; - } - - public static MembersInjector create(Provider protocolProvider) { - return new TestToken_MembersInjector(protocolProvider); - } - - @Override - public void injectMembers(TestToken instance) { - injectProtocol(instance, protocolProvider.get()); - } - - public static void injectProtocol(TestToken instance, Protocol protocol) { - instance.protocol = protocol; - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java deleted file mode 100644 index 1dc41bf0e16..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_DomainNameFactory implements Factory { - private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); - - @Override - public String get() { - return proxyDomainName(); - } - - public static TokenModule_DomainNameFactory create() { - return INSTANCE; - } - - public static String proxyDomainName() { - return Preconditions.checkNotNull( - TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java deleted file mode 100644 index afc66775c9d..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_ProvideTokenFactory implements Factory { - private final Provider tokenProvider; - - public TokenModule_ProvideTokenFactory(Provider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - @Override - public Token get() { - return proxyProvideToken(tokenProvider.get()); - } - - public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { - return new TokenModule_ProvideTokenFactory(tokenProvider); - } - - public static Token proxyProvideToken(WebWhoisToken token) { - return Preconditions.checkNotNull( - TokenModule.provideToken(token), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java deleted file mode 100644 index feab7f7d227..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.MembersInjector; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class Token_MembersInjector implements MembersInjector { - private final Provider actionHandlerProvider; - - public Token_MembersInjector(Provider actionHandlerProvider) { - this.actionHandlerProvider = actionHandlerProvider; - } - - public static MembersInjector create(Provider actionHandlerProvider) { - return new Token_MembersInjector(actionHandlerProvider); - } - - @Override - public void injectMembers(Token instance) { - injectActionHandler(instance, actionHandlerProvider.get()); - } - - public static void injectActionHandler(Object instance, ActionHandler actionHandler) { - ((Token) instance).actionHandler = actionHandler; - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java deleted file mode 100644 index 3d153c08fdb..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.Tokens; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisToken_Factory implements Factory { - private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); - - @Override - public WebWhoisToken get() { - return new WebWhoisToken(); - } - - public static WebWhoisToken_Factory create() { - return INSTANCE; - } - - public static WebWhoisToken newWebWhoisToken() { - return new WebWhoisToken(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java deleted file mode 100644 index f2f34a674d3..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpWhoisHostFactory implements Factory { - private static final WebWhoisModule_HttpWhoisHostFactory INSTANCE = - new WebWhoisModule_HttpWhoisHostFactory(); - - @Override - public String get() { - return proxyHttpWhoisHost(); - } - - public static WebWhoisModule_HttpWhoisHostFactory create() { - return INSTANCE; - } - - public static String proxyHttpWhoisHost() { - return Preconditions.checkNotNull( - WebWhoisModule.httpWhoisHost(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java deleted file mode 100644 index 67ab24c06fd..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpWhoisPathFactory implements Factory { - private static final WebWhoisModule_HttpWhoisPathFactory INSTANCE = - new WebWhoisModule_HttpWhoisPathFactory(); - - @Override - public String get() { - return proxyHttpWhoisPath(); - } - - public static WebWhoisModule_HttpWhoisPathFactory create() { - return INSTANCE; - } - - public static String proxyHttpWhoisPath() { - return Preconditions.checkNotNull( - WebWhoisModule.httpWhoisPath(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java deleted file mode 100644 index 4a29a990b67..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpWhoisPortFactory implements Factory { - private static final WebWhoisModule_HttpWhoisPortFactory INSTANCE = - new WebWhoisModule_HttpWhoisPortFactory(); - - @Override - public Integer get() { - return proxyHttpWhoisPort(); - } - - public static WebWhoisModule_HttpWhoisPortFactory create() { - return INSTANCE; - } - - public static int proxyHttpWhoisPort() { - return WebWhoisModule.httpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java deleted file mode 100644 index f8a7fae07a8..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpsWhoisHostFactory implements Factory { - private static final WebWhoisModule_HttpsWhoisHostFactory INSTANCE = - new WebWhoisModule_HttpsWhoisHostFactory(); - - @Override - public String get() { - return proxyHttpsWhoisHost(); - } - - public static WebWhoisModule_HttpsWhoisHostFactory create() { - return INSTANCE; - } - - public static String proxyHttpsWhoisHost() { - return Preconditions.checkNotNull( - WebWhoisModule.httpsWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java deleted file mode 100644 index 4cabb7b5384..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpsWhoisPathFactory implements Factory { - private static final WebWhoisModule_HttpsWhoisPathFactory INSTANCE = - new WebWhoisModule_HttpsWhoisPathFactory(); - - @Override - public String get() { - return proxyHttpsWhoisPath(); - } - - public static WebWhoisModule_HttpsWhoisPathFactory create() { - return INSTANCE; - } - - public static String proxyHttpsWhoisPath() { - return Preconditions.checkNotNull( - WebWhoisModule.httpsWhoisPath(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java deleted file mode 100644 index 30f4564213a..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpsWhoisPortFactory implements Factory { - private static final WebWhoisModule_HttpsWhoisPortFactory INSTANCE = - new WebWhoisModule_HttpsWhoisPortFactory(); - - @Override - public Integer get() { - return proxyHttpsWhoisPort(); - } - - public static WebWhoisModule_HttpsWhoisPortFactory create() { - return INSTANCE; - } - - public static int proxyHttpsWhoisPort() { - return WebWhoisModule.httpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java deleted file mode 100644 index 7c756174314..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpClientCodec; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpClientCodecFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = - new WebWhoisModule_ProvideHttpClientCodecFactory(); - - @Override - public HttpClientCodec get() { - return proxyProvideHttpClientCodec(); - } - - public static WebWhoisModule_ProvideHttpClientCodecFactory create() { - return INSTANCE; - } - - public static HttpClientCodec proxyProvideHttpClientCodec() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpClientCodec(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java deleted file mode 100644 index 20785cde372..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = - new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); - - @Override - public HttpObjectAggregator get() { - return proxyProvideHttpObjectAggregator(); - } - - public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { - return INSTANCE; - } - - public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpObjectAggregator(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java deleted file mode 100644 index 7087ab940bc..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public String get() { - return proxyProvideHttpWhoisHost(module); - } - - public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); - } - - public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { - return Preconditions.checkNotNull( - instance.provideHttpWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index a4aaf24978e..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisPortFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisPortFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static WebWhoisModule_ProvideHttpWhoisPortFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(WebWhoisModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index ed7e62f3a5f..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final Provider httpWhoisPortProvider; - - private final Provider httpWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpWhoisProtocolFactory( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpWhoisPortProvider = httpWhoisPortProvider; - this.httpWhoisHostProvider = httpWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpWhoisProtocol( - httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( - httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpWhoisProtocol( - int httpWhoisPort, - String httpWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index c3d7c6546e5..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisPortFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpsWhoisPortFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static WebWhoisModule_ProvideHttpsWhoisPortFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(WebWhoisModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index 4ab50681eea..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final Provider httpsWhoisPortProvider; - - private final Provider httpsWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpsWhoisPortProvider = httpsWhoisPortProvider; - this.httpsWhoisHostProvider = httpsWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpsWhoisProtocol( - httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpsWhoisProtocol( - int httpsWhoisPort, - String httpsWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java deleted file mode 100644 index 7579cc752cf..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { - private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = - new WebWhoisModule_ProvideSslProviderFactory(); - - @Override - public SslProvider get() { - return proxyProvideSslProvider(); - } - - public static WebWhoisModule_ProvideSslProviderFactory create() { - return INSTANCE; - } - - public static SslProvider proxyProvideSslProvider() { - return Preconditions.checkNotNull( - WebWhoisModule.provideSslProvider(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java deleted file mode 100644 index 37431babcb9..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpWhoisHandlerProviders( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java deleted file mode 100644 index adf393894e8..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider> sslClientInitializerProvider; - - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.sslClientInitializerProvider = sslClientInitializerProvider; - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpsWhoisHandlerProviders( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java deleted file mode 100644 index 6c840214a11..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisToken_Factory implements Factory { - private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); - - @Override - public WebWhoisToken get() { - return new WebWhoisToken(); - } - - public static WebWhoisToken_Factory create() { - return INSTANCE; - } - - public static WebWhoisToken newWebWhoisToken() { - return new WebWhoisToken(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java deleted file mode 100644 index d94df8b392f..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ActionHandler_Factory implements Factory { - private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); - - @Override - public ActionHandler get() { - return new ActionHandler(); - } - - public static ActionHandler_Factory create() { - return INSTANCE; - } - - public static ActionHandler newActionHandler() { - return new ActionHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java deleted file mode 100644 index ddf10cf830b..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class RedirectHandler_Factory implements Factory { - private static final RedirectHandler_Factory INSTANCE = new RedirectHandler_Factory(); - - @Override - public RedirectHandler get() { - return new RedirectHandler(); - } - - public static RedirectHandler_Factory create() { - return INSTANCE; - } - - public static RedirectHandler newRedirectHandler() { - return new RedirectHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java deleted file mode 100644 index 7fa480f418e..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import io.netty.channel.Channel; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class SslClientInitializer_Factory - implements Factory> { - private final Provider sslProvider; - - public SslClientInitializer_Factory(Provider sslProvider) { - this.sslProvider = sslProvider; - } - - @Override - public SslClientInitializer get() { - return new SslClientInitializer(sslProvider.get()); - } - - public static SslClientInitializer_Factory create( - Provider sslProvider) { - return new SslClientInitializer_Factory(sslProvider); - } - - public static SslClientInitializer newSslClientInitializer( - SslProvider sslProvider) { - return new SslClientInitializer(sslProvider); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java deleted file mode 100644 index 26b68fdc09c..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoIsHandler_Factory implements Factory { - private static final WebWhoIsHandler_Factory INSTANCE = new WebWhoIsHandler_Factory(); - - @Override - public WebWhoIsHandler get() { - return new WebWhoIsHandler(); - } - - public static WebWhoIsHandler_Factory create() { - return INSTANCE; - } - - public static WebWhoIsHandler newWebWhoIsHandler() { - return new WebWhoIsHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java deleted file mode 100644 index dc008e1a724..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisActionHandler_Factory implements Factory { - private static final WebWhoisActionHandler_Factory INSTANCE = new WebWhoisActionHandler_Factory(); - - @Override - public WebWhoisActionHandler get() { - return new WebWhoisActionHandler(); - } - - public static WebWhoisActionHandler_Factory create() { - return INSTANCE; - } - - public static WebWhoisActionHandler newWebWhoisActionHandler() { - return new WebWhoisActionHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java deleted file mode 100644 index b7971395941..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java +++ /dev/null @@ -1,155 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { - private final ProberModule proberModule; - - private Provider provideHttpWhoisPortProvider; - - private Provider provideHttpWhoisHostProvider; - - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider provideHttpsWhoisPortProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerProberModule_ProberComponent( - ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { - this.proberModule = proberModuleParam; - initialize(proberModuleParam, webWhoisModuleParam); - } - - public static Builder builder() { - return new Builder(); - } - - public static ProberModule.ProberComponent create() { - return new Builder().build(); - } - - private Set getSetOfProtocol() { - return ImmutableSet.of( - provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); - } - - private WebWhoisToken getWebWhoisToken() { - return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); - } - - @SuppressWarnings("unchecked") - private void initialize( - final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { - this.provideHttpWhoisPortProvider = - ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); - this.provideHttpWhoisHostProvider = - WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - provideHttpWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpWhoisHandlerProvidersProvider)); - this.provideHttpsWhoisPortProvider = - ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - provideHttpsWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public ImmutableMap providePortToProtocolMap() { - return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( - proberModule, getSetOfProtocol()); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); - } - - public static final class Builder { - private ProberModule proberModule; - - private WebWhoisModule webWhoisModule; - - private Builder() {} - - public Builder proberModule(ProberModule proberModule) { - this.proberModule = Preconditions.checkNotNull(proberModule); - return this; - } - - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public ProberModule.ProberComponent build() { - if (proberModule == null) { - this.proberModule = new ProberModule(); - } - if (webWhoisModule == null) { - this.webWhoisModule = new WebWhoisModule(); - } - return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); - } - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index 955698498db..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(ProberModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index 0b97c8dbb72..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(ProberModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java deleted file mode 100644 index e0597aa25f5..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableMap; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvidePortToProtocolMapFactory - implements Factory> { - private final ProberModule module; - - private final Provider> protocolSetProvider; - - public ProberModule_ProvidePortToProtocolMapFactory( - ProberModule module, Provider> protocolSetProvider) { - this.module = module; - this.protocolSetProvider = protocolSetProvider; - } - - @Override - public ImmutableMap get() { - return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); - } - - public static ProberModule_ProvidePortToProtocolMapFactory create( - ProberModule module, Provider> protocolSetProvider) { - return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); - } - - public static ImmutableMap proxyProvidePortToProtocolMap( - ProberModule instance, Set protocolSet) { - return Preconditions.checkNotNull( - instance.providePortToProtocolMap(protocolSet), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java deleted file mode 100644 index 20e2ca11502..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_DomainNameFactory implements Factory { - private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); - - @Override - public String get() { - return proxyDomainName(); - } - - public static TokenModule_DomainNameFactory create() { - return INSTANCE; - } - - public static String proxyDomainName() { - return Preconditions.checkNotNull( - TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java deleted file mode 100644 index e6628332802..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_ProvideTokenFactory implements Factory { - private final Provider tokenProvider; - - public TokenModule_ProvideTokenFactory(Provider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - @Override - public Token get() { - return proxyProvideToken(tokenProvider.get()); - } - - public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { - return new TokenModule_ProvideTokenFactory(tokenProvider); - } - - public static Token proxyProvideToken(WebWhoisToken token) { - return Preconditions.checkNotNull( - TokenModule.provideToken(token), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java deleted file mode 100644 index 31710bed6eb..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpClientCodec; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpClientCodecFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = - new WebWhoisModule_ProvideHttpClientCodecFactory(); - - @Override - public HttpClientCodec get() { - return proxyProvideHttpClientCodec(); - } - - public static WebWhoisModule_ProvideHttpClientCodecFactory create() { - return INSTANCE; - } - - public static HttpClientCodec proxyProvideHttpClientCodec() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpClientCodec(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java deleted file mode 100644 index b69df1a2f7d..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = - new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); - - @Override - public HttpObjectAggregator get() { - return proxyProvideHttpObjectAggregator(); - } - - public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { - return INSTANCE; - } - - public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpObjectAggregator(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java deleted file mode 100644 index bacebd82f49..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public String get() { - return proxyProvideHttpWhoisHost(module); - } - - public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); - } - - public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { - return Preconditions.checkNotNull( - instance.provideHttpWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index 0d098288569..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final Provider httpWhoisPortProvider; - - private final Provider httpWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpWhoisProtocolFactory( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpWhoisPortProvider = httpWhoisPortProvider; - this.httpWhoisHostProvider = httpWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpWhoisProtocol( - httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( - httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpWhoisProtocol( - int httpWhoisPort, - String httpWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index c40cde16709..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final Provider httpsWhoisPortProvider; - - private final Provider httpsWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpsWhoisPortProvider = httpsWhoisPortProvider; - this.httpsWhoisHostProvider = httpsWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpsWhoisProtocol( - httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpsWhoisProtocol( - int httpsWhoisPort, - String httpsWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java deleted file mode 100644 index 208d9c7212e..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { - private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = - new WebWhoisModule_ProvideSslProviderFactory(); - - @Override - public SslProvider get() { - return proxyProvideSslProvider(); - } - - public static WebWhoisModule_ProvideSslProviderFactory create() { - return INSTANCE; - } - - public static SslProvider proxyProvideSslProvider() { - return Preconditions.checkNotNull( - WebWhoisModule.provideSslProvider(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java deleted file mode 100644 index 81eb6efc487..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpWhoisHandlerProviders( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java deleted file mode 100644 index e18a43dd7a8..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider> sslClientInitializerProvider; - - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.sslClientInitializerProvider = sslClientInitializerProvider; - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpsWhoisHandlerProviders( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java deleted file mode 100644 index 39af08b1e60..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java +++ /dev/null @@ -1,154 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { - private final ProberModule proberModule; - - private Provider provideHttpWhoisPortProvider; - - private Provider provideHttpWhoisHostProvider; - - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider provideHttpsWhoisPortProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerProberModule_ProberComponent( - ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { - this.proberModule = proberModuleParam; - initialize(proberModuleParam, webWhoisModuleParam); - } - - public static Builder builder() { - return new Builder(); - } - - public static ProberModule.ProberComponent create() { - return new Builder().build(); - } - - private Set getSetOfProtocol() { - return ImmutableSet.of( - provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); - } - - private WebWhoisToken getWebWhoisToken() { - return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); - } - - @SuppressWarnings("unchecked") - private void initialize( - final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { - this.provideHttpWhoisPortProvider = - ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); - this.provideHttpWhoisHostProvider = - WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - provideHttpWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpWhoisHandlerProvidersProvider)); - this.provideHttpsWhoisPortProvider = - ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - provideHttpsWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public ImmutableMap providePortToProtocolMap() { - return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( - proberModule, getSetOfProtocol()); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); - } - - public static final class Builder { - private ProberModule proberModule; - - private WebWhoisModule webWhoisModule; - - private Builder() {} - - public Builder proberModule(ProberModule proberModule) { - this.proberModule = Preconditions.checkNotNull(proberModule); - return this; - } - - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public ProberModule.ProberComponent build() { - if (proberModule == null) { - this.proberModule = new ProberModule(); - } - if (webWhoisModule == null) { - this.webWhoisModule = new WebWhoisModule(); - } - return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); - } - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java deleted file mode 100644 index 45032a9c7ba..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java +++ /dev/null @@ -1,46 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerTestModule_TestComponent implements TestModule.TestComponent { - private DaggerTestModule_TestComponent() {} - - public static Builder builder() { - return new Builder(); - } - - public static TestModule.TestComponent create() { - return new Builder().build(); - } - - @Override - public ImmutableList> provideHandlers() { - return TestModule_ProvideHandlersFactory.proxyProvideHandlers(TestHandler_Factory.create()); - } - - public static final class Builder { - private Builder() {} - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder testModule(TestModule testModule) { - Preconditions.checkNotNull(testModule); - return this; - } - - public TestModule.TestComponent build() { - return new DaggerTestModule_TestComponent(); - } - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index 93f9e4f9f48..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(ProberModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index 0aee5faf959..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(ProberModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java deleted file mode 100644 index 7ab2e4e9dd9..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableMap; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvidePortToProtocolMapFactory - implements Factory> { - private final ProberModule module; - - private final Provider> protocolSetProvider; - - public ProberModule_ProvidePortToProtocolMapFactory( - ProberModule module, Provider> protocolSetProvider) { - this.module = module; - this.protocolSetProvider = protocolSetProvider; - } - - @Override - public ImmutableMap get() { - return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); - } - - public static ProberModule_ProvidePortToProtocolMapFactory create( - ProberModule module, Provider> protocolSetProvider) { - return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); - } - - public static ImmutableMap proxyProvidePortToProtocolMap( - ProberModule instance, Set protocolSet) { - return Preconditions.checkNotNull( - instance.providePortToProtocolMap(protocolSet), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java deleted file mode 100644 index 50616d20699..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestHandler_Factory implements Factory { - private static final TestHandler_Factory INSTANCE = new TestHandler_Factory(); - - @Override - public TestHandler get() { - return new TestHandler(); - } - - public static TestHandler_Factory create() { - return INSTANCE; - } - - public static TestHandler newTestHandler() { - return new TestHandler(); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java deleted file mode 100644 index 79e40ee2d4a..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestModule_ProvideHandlersFactory - implements Factory>> { - private final Provider testHandlerProvider; - - public TestModule_ProvideHandlersFactory(Provider testHandlerProvider) { - this.testHandlerProvider = testHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProvideHandlers(testHandlerProvider); - } - - public static TestModule_ProvideHandlersFactory create( - Provider testHandlerProvider) { - return new TestModule_ProvideHandlersFactory(testHandlerProvider); - } - - public static ImmutableList> proxyProvideHandlers( - Provider testHandlerProvider) { - return Preconditions.checkNotNull( - TestModule.provideHandlers(testHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java deleted file mode 100644 index 75b788ec968..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java +++ /dev/null @@ -1,36 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.MembersInjector; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestProtocol_MembersInjector implements MembersInjector { - private final Provider>> - handlerProvidersProvider; - - public TestProtocol_MembersInjector( - Provider>> handlerProvidersProvider) { - this.handlerProvidersProvider = handlerProvidersProvider; - } - - public static MembersInjector create( - Provider>> handlerProvidersProvider) { - return new TestProtocol_MembersInjector(handlerProvidersProvider); - } - - @Override - public void injectMembers(TestProtocol instance) { - injectTestProtocolHandlers(instance, handlerProvidersProvider.get()); - } - - public static void injectTestProtocolHandlers( - TestProtocol instance, ImmutableList> handlerProviders) { - instance.TestProtocolHandlers(handlerProviders); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java deleted file mode 100644 index 1dc41bf0e16..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_DomainNameFactory implements Factory { - private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); - - @Override - public String get() { - return proxyDomainName(); - } - - public static TokenModule_DomainNameFactory create() { - return INSTANCE; - } - - public static String proxyDomainName() { - return Preconditions.checkNotNull( - TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java deleted file mode 100644 index afc66775c9d..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_ProvideTokenFactory implements Factory { - private final Provider tokenProvider; - - public TokenModule_ProvideTokenFactory(Provider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - @Override - public Token get() { - return proxyProvideToken(tokenProvider.get()); - } - - public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { - return new TokenModule_ProvideTokenFactory(tokenProvider); - } - - public static Token proxyProvideToken(WebWhoisToken token) { - return Preconditions.checkNotNull( - TokenModule.provideToken(token), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java deleted file mode 100644 index 7c756174314..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpClientCodec; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpClientCodecFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = - new WebWhoisModule_ProvideHttpClientCodecFactory(); - - @Override - public HttpClientCodec get() { - return proxyProvideHttpClientCodec(); - } - - public static WebWhoisModule_ProvideHttpClientCodecFactory create() { - return INSTANCE; - } - - public static HttpClientCodec proxyProvideHttpClientCodec() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpClientCodec(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java deleted file mode 100644 index 20785cde372..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = - new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); - - @Override - public HttpObjectAggregator get() { - return proxyProvideHttpObjectAggregator(); - } - - public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { - return INSTANCE; - } - - public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpObjectAggregator(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java deleted file mode 100644 index 7087ab940bc..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public String get() { - return proxyProvideHttpWhoisHost(module); - } - - public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); - } - - public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { - return Preconditions.checkNotNull( - instance.provideHttpWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index ed7e62f3a5f..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final Provider httpWhoisPortProvider; - - private final Provider httpWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpWhoisProtocolFactory( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpWhoisPortProvider = httpWhoisPortProvider; - this.httpWhoisHostProvider = httpWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpWhoisProtocol( - httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( - httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpWhoisProtocol( - int httpWhoisPort, - String httpWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index 4ab50681eea..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final Provider httpsWhoisPortProvider; - - private final Provider httpsWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpsWhoisPortProvider = httpsWhoisPortProvider; - this.httpsWhoisHostProvider = httpsWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpsWhoisProtocol( - httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpsWhoisProtocol( - int httpsWhoisPort, - String httpsWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java deleted file mode 100644 index 7579cc752cf..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { - private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = - new WebWhoisModule_ProvideSslProviderFactory(); - - @Override - public SslProvider get() { - return proxyProvideSslProvider(); - } - - public static WebWhoisModule_ProvideSslProviderFactory create() { - return INSTANCE; - } - - public static SslProvider proxyProvideSslProvider() { - return Preconditions.checkNotNull( - WebWhoisModule.provideSslProvider(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java deleted file mode 100644 index 37431babcb9..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpWhoisHandlerProviders( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java deleted file mode 100644 index adf393894e8..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider> sslClientInitializerProvider; - - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.sslClientInitializerProvider = sslClientInitializerProvider; - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpsWhoisHandlerProviders( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} From 7836c3f704486ba5efec1d416569260895da6442 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 16:56:54 -0400 Subject: [PATCH 010/337] Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class --- .../monitoring/blackbox/ProbingAction.java | 156 +++++++++++ .../monitoring/blackbox/Protocol.java | 16 +- .../handlers/SslClientInitializer.java | 53 +--- .../handlers/WebWhoisActionHandler.java | 186 ++++--------- .../monitoring/blackbox/TestUtils.java | 109 ++++++-- .../blackbox/handlers/NettyRule.java | 122 ++++----- .../blackbox/handlers/RedirectHandler.java | 5 + .../handlers/SslClientInitializerTest.java | 57 ++-- .../handlers/SslInitializerTestUtils.java | 3 +- .../handlers/WebWhoisActionHandlerTest.java | 254 ++++++++---------- 10 files changed, 521 insertions(+), 440 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java new file mode 100644 index 00000000000..6fbcadaf999 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -0,0 +1,156 @@ +// 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.monitoring.blackbox; + +import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import io.netty.util.AttributeKey; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; +import java.util.concurrent.Callable; +import javax.inject.Provider; + +/** + *Class that represents given action in sequence of probing + * + */ + + +public abstract class ProbingAction implements Callable { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Attribute Key that links channel to its {@link ProbingAction}*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** {@link ActionHandler} Associated with this {@link ProbingAction}*/ + private ActionHandler actionHandler; + + + /** + * The requisite instance of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline + */ + public ActionHandler actionHandler() { + return actionHandler; + } + + + /** {@link Timer} that rate limits probing*/ + private static final Timer timer = new HashedWheelTimer(); + + + /** actual {@link Duration} of this delay*/ + public abstract Duration delay(); + + /** message to send to server */ + public abstract O outboundMessage(); + + /** + * @return {@link Channel} object that represents connection between prober client and server + */ + public abstract Channel channel(); + + /** + * @return The {@link Protocol} instance that represents action to be tested by this part in sequences + */ + public abstract Protocol protocol(); + + /** + * + * @return {@link Builder} that lets us build a new ProbingAction by customizing abstract methods + */ + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** + * The method that calls the {@link ActionHandler} to send a message down the channel pipeline + * @return future that denotes when the action has been successfully performed + */ + + @Override + public ChannelFuture call() { + + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch(ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + } + + + + + ChannelPromise finished = channel().newPromise(); + + //Every specified time frame by delay(), we perform the next action in our sequence + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + ChannelFuture channelFuture = actionHandler().apply(outboundMessage()); + + channelFuture.addListeners( + future -> actionHandler().resetFuture(), + future -> finished.setSuccess()); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + + return finished; + } + + public abstract static class Builder, P extends ProbingAction> { + + public abstract B delay(Duration value); + + public abstract B outboundMessage(O value); + + public abstract B protocol(Protocol value); + + abstract P autoBuild(); + + public P build() { + P probingAction = autoBuild(); + probingAction.protocol().probingAction(probingAction); + return probingAction; + } + } + /** + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified + */ + static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); + } + } + +} + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 50a1d90a12c..913b7d7627e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -28,6 +28,8 @@ @AutoValue public abstract class Protocol { + public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + /** * Default names associated with each protocol */ @@ -38,6 +40,7 @@ public abstract class Protocol { private String host; private String path = ""; + private ProbingAction probingAction; /** Setter method for Protocol's host*/ public Protocol host(String host) { @@ -61,6 +64,17 @@ public String path() { return path; } + /** Setter method for Protocol's ProbingAction parent*/ + public Protocol probingAction(ProbingAction probingAction) { + this.probingAction = probingAction; + return this; + } + + /** Getter method for Protocol's path*/ + public ProbingAction probingAction() { + return probingAction; + } + /** If connection associated with Protocol is persistent, which is only EPP */ public boolean persistentConnection() { return name() == EPP_PROTOCOL_NAME; @@ -78,7 +92,7 @@ public boolean persistentConnection() { public abstract Builder toBuilder(); - public static Protocol.Builder builder() { + public static Builder builder() { return new AutoValue_Protocol.Builder(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index c62668b19b2..eeecb468fce 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -15,11 +15,12 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; + import google.registry.monitoring.blackbox.Protocol; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler.Sharable; @@ -28,9 +29,8 @@ import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslHandler; import io.netty.handler.ssl.SslProvider; -import java.security.PrivateKey; import java.security.cert.X509Certificate; -import java.util.function.Supplier; +import javax.inject.Inject; import javax.inject.Singleton; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; @@ -38,9 +38,6 @@ /** * Adds a client side SSL handler to the channel pipeline. * - *

Code is close to unchanged from {@link SslClientInitializer}

in proxy, but is modified - * for revised overall structure of connections, and to accomdate EPP connections

- * *

This must be the first handler provided for any handler provider list, if it is * provided. The type parameter {@code C} is needed so that unit tests can construct this handler * that works with {@link EmbeddedChannel}; @@ -53,59 +50,30 @@ public class SslClientInitializer extends ChannelInitializer< private final SslProvider sslProvider; private final X509Certificate[] trustedCertificates; - private final Supplier privateKeySupplier; - private final Supplier certificateSupplier; - + @Inject public SslClientInitializer(SslProvider sslProvider) { // null uses the system default trust store. - //Used for WebWhois, so we don't care about privateKey and certificates, setting them to null - this(sslProvider, null, null, null); - } - - public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, - Supplier certificateSupplier) { - //We use the default trust store here as well, setting trustCertificates to null - this(sslProvider, null, privateKeySupplier, certificateSupplier); + this(sslProvider, null); } @VisibleForTesting SslClientInitializer(SslProvider sslProvider, X509Certificate[] trustCertificates) { - this(sslProvider, trustCertificates, null, null); - } - - private SslClientInitializer( - SslProvider sslProvider, - X509Certificate[] trustCertificates, - Supplier privateKeySupplier, - Supplier certificateSupplier) { logger.atInfo().log("Client SSL Provider: %s", sslProvider); - this.sslProvider = sslProvider; this.trustedCertificates = trustCertificates; - this.privateKeySupplier = privateKeySupplier; - this.certificateSupplier = certificateSupplier; } @Override protected void initChannel(C channel) throws Exception { Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - String host = channel.attr(REMOTE_ADDRESS_KEY).get(); - - //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); - SslContextBuilder sslContextBuilder = + SslHandler sslHandler = SslContextBuilder.forClient() .sslProvider(sslProvider) - .trustManager(trustedCertificates); - if (privateKeySupplier != null && certificateSupplier != null) { - sslContextBuilder = sslContextBuilder - .keyManager(privateKeySupplier.get(), certificateSupplier.get()); - } - - SslHandler sslHandler = sslContextBuilder - .build() - .newHandler(channel.alloc(), host, protocol.port()); + .trustManager(trustedCertificates) + .build() + .newHandler(channel.alloc(), protocol.host(), protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); @@ -116,4 +84,3 @@ protected void initChannel(C channel) throws Exception { channel.pipeline().addLast(sslHandler); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index c56c8c7d97c..1a1664a3c3c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. @@ -14,176 +14,92 @@ package google.registry.monitoring.blackbox.handlers; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import java.net.MalformedURLException; import java.net.URL; import javax.inject.Inject; -import org.joda.time.Duration; -/** - * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence - * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response - * implies a redirection it follows the redirection until either an Error Response is received, or - * {@link HttpResponseStatus.OK} is received

- */ -public class WebWhoisActionHandler extends ActionHandler { +public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** - * {@link Bootstrap} necessary for remaking connection on redirect response. - */ - private final Bootstrap bootstrap; - - /** - * {@link Protocol} for when redirected to http endpoint. - */ - private final Protocol httpWhoisProtocol; - - /** - * {@link Protocol} for when redirected to https endpoint. - */ - private final Protocol httpsWhoisProtocol; - - /** - * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. - */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } - + public WebWhoisActionHandler() {} - /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, - * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a - * response indicating a Failure, or receives a redirection response, where it follows the - * redirects until receiving one of the previous three responses. - */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { - - HttpResponseMessage response = (HttpResponseMessage) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpResponse response) throws Exception{ + if (response.status() == HttpResponseStatus.OK) { + logger.atInfo().log("Recieved Successful HttpResponseStatus"); + finished.setSuccess(); + System.out.println(response); - if (response.status().equals(HttpResponseStatus.OK)) { - logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - - //On success, we always pass message to ActionHandler's channelRead0 method. - super.channelRead0(ctx, msg); - - } else if (response.status().equals(HttpResponseStatus.MOVED_PERMANENTLY) - || response.status().equals(HttpResponseStatus.FOUND)) { - //TODO - Fix checker to better determine when we have encountered a redirection response. + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { //Obtain url to be redirected to - URL url; - try { - url = new URL(response.headers().get("Location")); - } catch (MalformedURLException e) { - //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException( - "Redirected Location was invalid. Given Location was: " + response.headers() - .get("Location")); - } + URL url = new URL(response.headers().get("Location")); + //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); + int newPort = url.getDefaultPort(); - logger.atInfo().log(String - .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, - url.getDefaultPort(), newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); + + + Protocol oldProtocol = ctx.channel().attr(PROTOCOL_KEY).get(); + + //Build new Protocol from new attributes + ProbingAction currentAction = oldProtocol.probingAction(); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException( - "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); - } - - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); - - //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + Protocol newProtocol = Prober.portToProtocolMap.get(newPort).toBuilder().build() + .host(newHost) + .path(newPath); + + //Modify HttpRequest sent to remote host to reflect new path and host + FullHttpRequest httpRequest = ((DefaultFullHttpRequest) currentAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + + + //Create new probingAction that takes in the new Protocol and HttpRequest message + ProbingAction redirectedAction = currentAction., NewChannelAction>toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) .build(); + oldProtocol.probingAction(redirectedAction); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } - - //Once channel is closed, establish new connection to redirected host, and repeat - // same actions + logger.atInfo().log("Successfully Closed Connection"); + + //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell - // ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { - //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); + finished.setFailure(new RuntimeException()); + logger.atWarning().log(String.format("Received Response: %s", response.status())); } } - - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 66e2928f45e..5d9a8b5a977 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,23 +14,40 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.cookie.ClientCookieEncoder; +import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.ServerCookieEncoder; -/** - * Utility class for various helper methods used in testing. - */ +/** Utility class for various helper methods used in testing. */ public class TestUtils { + public static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -51,20 +68,80 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { return response; } - /** - * Creates HttpResponse given status, redirection location, and other necessary inputs - */ - public static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain"); - if (location != null) { - response.headers().set("location", location); + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpRequest makeEppHttpRequest( + String content, + String host, + String path, + String accessToken, + String sslClientCertificateHash, + String clientAddress, + Cookie... cookies) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "application/epp+xml") + .set("accept", "application/epp+xml") + .set("X-SSL-Certificate", sslClientCertificateHash) + .set("X-Forwarded-For", clientAddress); + if (cookies.length != 0) { + request.headers().set("cookie", ClientCookieEncoder.STRICT.encode(cookies)); } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); + return response; + } + + public static FullHttpResponse makeEppHttpResponse( + String content, HttpResponseStatus status, Cookie... cookies) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "application/epp+xml"); + for (Cookie cookie : cookies) { + response.headers().add("set-cookie", ServerCookieEncoder.STRICT.encode(cookie)); } return response; } -} + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 4b6eed9c16f..399bc9c4c35 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. @@ -16,20 +16,17 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; + import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingActionTest; -import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.testservers.TestServer; import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -41,6 +38,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -51,54 +49,49 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest} - *

+ *

Used in {@link SslClientInitializerTest} */ -public final class NettyRule extends ExternalResource { +final class NettyRule extends ExternalResource { + // All I/O operations are done inside the single thread within this event loop group, which is + // different from the main test thread. Therefore synchronizations are required to make sure that + // certain I/O activities are finished when assertions are performed. + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final EventLoopGroup eventLoopGroup; // Handler attached to server's channel to record the request received. private EchoHandler echoHandler; + // Handler attached to client's channel to record the response received. private DumpHandler dumpHandler; - private Channel channel; - - // All I/O operations are done inside the single thread within this event loop group, which is - // different from the main test thread. Therefore synchronizations are required to make sure that - // certain I/O activities are finished when assertions are performed. - public NettyRule() { - eventLoopGroup = new NioEventLoopGroup(1); - } - public NettyRule(EventLoopGroup e) { - eventLoopGroup = e; - } - - private static void writeToChannelAndFlush(Channel channel, String data) { - ChannelFuture unusedFuture = - channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); - } + private Channel channel; - /** - * Sets up a server channel bound to the given local address. - */ - public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { + /** Sets up a server channel bound to the given local address. */ + void setUpServer(LocalAddress localAddress, ChannelHandler handler) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - - new TestServer(eventLoopGroup, localAddress, - ImmutableList.builder().add(handlers).add(echoHandler).build()); + ChannelInitializer serverInitializer = + new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) { + // Add the given handler + ch.pipeline().addLast(handler); + // Add the "echoHandler" last to log the incoming message and send it back + ch.pipeline().addLast(echoHandler); + } + }; + ServerBootstrap sb = + new ServerBootstrap() + .group(eventLoopGroup) + .channel(LocalServerChannel.class) + .childHandler(serverInitializer); + ChannelFuture unusedFuture = sb.bind(localAddress).syncUninterruptibly(); } - /** - * Sets up a client channel connecting to the give local address. - */ + /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, Protocol protocol, - String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -118,30 +111,20 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol) - .attr(REMOTE_ADDRESS_KEY, host); - + .attr(PROTOCOL_KEY, protocol); channel = b.connect(localAddress).syncUninterruptibly().channel(); } - private void checkReady() { + void checkReady() { checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); } - /** - * Test that custom setup to send message to current server sends right message - */ - public void assertReceivedMessage(String message) throws Exception { - assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); - - } - /** * Test that a message can go through, both inbound and outbound. * - *

The client writes the message to the server, which echos it back and saves the string in - * its promise. The client receives the echo and saves it in its promise. All these activities - * happens in the I/O thread, and this call itself returns immediately. + *

The client writes the message to the server, which echos it back and saves the string in its + * promise. The client receives the echo and saves it in its promise. All these activities happens + * in the I/O thread, and this call itself returns immediately. */ void assertThatMessagesWork() throws Exception { checkReady(); @@ -171,27 +154,21 @@ ThrowableSubject assertThatClientRootCause() { assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); } - @Override - protected void after() { - Future unusedFuture = eventLoopGroup.shutdownGracefully(); - } - /** * A handler that echoes back its inbound message. The message is also saved in a promise for * inspection later. */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { + private static class EchoHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture requestFuture = new CompletableFuture<>(); - public Future getRequestFuture() { + Future getRequestFuture() { return requestFuture; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // In the test we only send messages of type ByteBuf. - assertThat(msg).isInstanceOf(ByteBuf.class); String request = ((ByteBuf) msg).toString(UTF_8); // After the message is written back to the client, fulfill the promise. @@ -199,9 +176,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); } - /** - * Saves any inbound error as the cause of the promise failure. - */ + /** Saves any inbound error as the cause of the promise failure. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ChannelFuture unusedFuture = @@ -209,9 +184,7 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E } } - /** - * A handler that dumps its inbound message to a promise that can be inspected later. - */ + /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture responseFuture = new CompletableFuture<>(); @@ -232,13 +205,20 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception responseFuture.complete(response); } - /** - * Saves any inbound error into the failure cause of the promise. - */ + /** Saves any inbound error into the failure cause of the promise. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); } } -} + @Override + protected void after() { + Future unusedFuture = eventLoopGroup.shutdownGracefully(); + } + + private static void writeToChannelAndFlush(Channel channel, String data) { + ChannelFuture unusedFuture = + channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java new file mode 100644 index 00000000000..f7af491e39e --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox.handlers; + +public class RedirectHandler { + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 2a9f9758e09..6725643c48d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -15,7 +15,6 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; @@ -62,41 +61,38 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - /** - * Fake host to test if the SSL engine gets the correct peer host. - */ + /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; - /** - * Fake port to test if the SSL engine gets the correct peer port. - */ + /** Fake port to test if the SSL engine gets the correct peer port. */ private static final int SSL_PORT = 12345; - /** - * Fake protocol saved in channel attribute. - */ - private static final Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + @Rule public NettyRule nettyRule = new NettyRule(); + @Parameter(0) public SslProvider sslProvider; - /** - * Saves the SNI hostname received by the server, if sent by the client. - */ - private String sniHostReceived; // We do our best effort to test all available SSL providers. @Parameters(name = "{0}") public static SslProvider[] data() { return OpenSsl.isAvailable() - ? new SslProvider[]{SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[]{SslProvider.JDK}; + ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[] {SslProvider.JDK}; } + /** Saves the SNI hostname received by the server, if sent by the client. */ + private String sniHostReceived; + + /** Fake protocol saved in channel attribute. */ + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .build() + .host(SSL_HOST); + private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { SslContext sslContext = SslContextBuilder.forServer(privateKey, certificate).build(); @@ -113,7 +109,6 @@ public void testSuccess_swappedInitializerWithSslHandler() throws Exception { new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); channel.attr(PROTOCOL_KEY).set(PROTOCOL); - channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -143,8 +138,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except nettyRule.setUpServer(localAddress, getServerHandler(ssc.key(), ssc.cert())); SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -170,9 +164,8 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); - - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -199,9 +192,8 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); - - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. @@ -211,4 +203,3 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E assertThat(nettyRule.getChannel().isActive()).isFalse(); } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java index 68b2919141d..7b4aae50106 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -92,4 +92,3 @@ static SSLSession setUpSslChannel( return sslHandler.engine().getSession(); } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index a4c2c57dc1a..001c935d70a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -1,232 +1,208 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; + import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import google.registry.monitoring.blackbox.testservers.TestServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelPromise; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import javax.inject.Provider; +import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@link WebWhoisActionHandler}. - * - *

Attempts to test how well {@link WebWhoisActionHandler} works - * when responding to all possible types of responses

- */ +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; + private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; + private static final String HTTPS_REDIRECT = "https://"; + private static final String REDIRECT_HOST = "www.example.com"; + private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; - private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private final Protocol standardProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( - null, null, null, null))) - .setName("http") - .setPersistentConnection(false) - .setPort(HTTP_PORT) - .build(); + private static final Duration DEFAULT_DURATION = new Duration(0L); private EmbeddedChannel channel; private ActionHandler actionHandler; - private Provider actionHandlerProvider; - private Protocol initialProtocol; - private HttpRequestMessage msg; - - /** - * Creates default protocol with empty list of handlers and specified other inputs - */ - private Protocol createProtocol(String name, int port, boolean persistentConnection) { + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() - .setName(name) - .setPort(port) - .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) - .setPersistentConnection(persistentConnection) - .build(); + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); } - /** - * Initializes new WebWhoisActionHandler - */ - private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { - actionHandler = new WebWhoisActionHandler( - bootstrap, - standardProtocol, - standardProtocol, - messageTemplate - ); - actionHandlerProvider = () -> actionHandler; + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); } - /** - * Sets up testing channel with requisite attributes - */ + /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol) { + setupActionHandler(); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - private Bootstrap makeBootstrap(EventLoopGroup group) { - return new Bootstrap() - .group(group) - .channel(LocalChannel.class); + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); } + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); + } - private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { - msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); - setupActionHandler(bootstrap, msg); - initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; } + @Test - public void testBasic_responseOk() { + public void testSuccess_responseOk() { //setup - setup("", null, true); + Protocol initialProtocol = createProtocol("responseOk", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); - //assesses that we successfully received good response and protocol is unchanged + //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badRequest() { + public void testSuccess_responseBad() { //setup - setup("", null, false); + Protocol initialProtocol = createProtocol("responseBad", 0, ""); setupChannel(initialProtocol); - // Stores future that informs when action is completed. - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + //stores future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage( - makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); - // Assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); - // Assesses that listener is triggered, but event is not success - assertThat(future.isDone()).isTrue(); + //assesses that listener is triggered, but event is not success + assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isFalse(); - // Ensures that we fail as a result of a FailureException. - assertThat(future.cause() instanceof FailureException).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badURL() { + public void testSuccess_redirectCloseChannel() { //setup - setup("", null, false); - setupChannel(initialProtocol); + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true)); + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, and event is success - assertThat(future.isDone()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + - // Ensures that we fail as a result of a FailureException. - assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testAdvanced_redirect() { - // Sets up EventLoopGroup with 1 thread to be blocking. - EventLoopGroup group = new NioEventLoopGroup(1); - - // Sets up embedded channel. - setup("", makeBootstrap(group), false); - setupChannel(initialProtocol); - - // Initializes LocalAddress with unique String. - LocalAddress address = new LocalAddress(TARGET_HOST); - - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - // Path that we test WebWhoisActionHandler uses. - String path = "/test"; + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - // Sets up the local server that the handler will be redirected to. - TestServer.webWhoisServer(group, address, "", TARGET_HOST, path); - FullHttpResponse response = - new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + TARGET_HOST + path, true)); + channel.writeInbound(originalResponse); - //checks that future has not been set to successful or a failure - assertThat(future.isDone()).isFalse(); + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); - channel.writeInbound(response); + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } + } From 8332d1e503ddf253d818f291106dbac1faf0d33f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 16:58:33 -0400 Subject: [PATCH 011/337] Fixed build.gradle changes requested --- prober/build.gradle | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index fe5e08a62f5..e826fb6c37a 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -5,21 +5,13 @@ createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober dependencies { def deps = rootProject.dependencyMap - - compile deps['com.beust:jcommander'] - compile deps['com.google.api-client:google-api-client'] - compile deps['com.google.apis:google-api-services-cloudkms'] - compile deps['com.google.apis:google-api-services-monitoring'] - compile deps['com.google.apis:google-api-services-storage'] + compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] - compile deps['com.google.http-client:google-http-client'] - compile deps['com.google.monitoring-client:metrics'] - compile deps['com.google.monitoring-client:stackdriver'] compile deps['io.netty:netty-buffer'] compile deps['io.netty:netty-codec-http'] compile deps['io.netty:netty-codec'] @@ -35,10 +27,8 @@ dependencies { runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - - testCompile deps['com.google.monitoring-client:contrib'] + testCompile deps['com.google.truth:truth'] - testCompile deps['org.yaml:snakeyaml'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') From 988f231a743081f99fa11d85688e2e40016ac336 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:04:45 -0400 Subject: [PATCH 012/337] Removed Files irrelevant to current pull request --- .../monitoring/blackbox/ProbingAction.java | 156 ------------ .../handlers/SslClientInitializer.java | 86 ------- .../handlers/WebWhoisActionHandler.java | 105 -------- .../blackbox/Handlers/ActionHandlerTest.java | 85 ------- .../monitoring/blackbox/TestUtils.java | 147 ------------ .../blackbox/handlers/NettyRule.java | 224 ------------------ .../blackbox/handlers/RedirectHandler.java | 5 - .../handlers/SslClientInitializerTest.java | 205 ---------------- .../handlers/SslInitializerTestUtils.java | 94 -------- .../handlers/WebWhoisActionHandlerTest.java | 208 ---------------- 10 files changed, 1315 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java deleted file mode 100644 index 6fbcadaf999..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ /dev/null @@ -1,156 +0,0 @@ -// 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.monitoring.blackbox; - -import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import io.netty.util.AttributeKey; -import java.util.concurrent.TimeUnit; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; -import javax.inject.Provider; - -/** - *Class that represents given action in sequence of probing - * - */ - - -public abstract class ProbingAction implements Callable { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** Attribute Key that links channel to its {@link ProbingAction}*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** {@link ActionHandler} Associated with this {@link ProbingAction}*/ - private ActionHandler actionHandler; - - - /** - * The requisite instance of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline - */ - public ActionHandler actionHandler() { - return actionHandler; - } - - - /** {@link Timer} that rate limits probing*/ - private static final Timer timer = new HashedWheelTimer(); - - - /** actual {@link Duration} of this delay*/ - public abstract Duration delay(); - - /** message to send to server */ - public abstract O outboundMessage(); - - /** - * @return {@link Channel} object that represents connection between prober client and server - */ - public abstract Channel channel(); - - /** - * @return The {@link Protocol} instance that represents action to be tested by this part in sequences - */ - public abstract Protocol protocol(); - - /** - * - * @return {@link Builder} that lets us build a new ProbingAction by customizing abstract methods - */ - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** - * The method that calls the {@link ActionHandler} to send a message down the channel pipeline - * @return future that denotes when the action has been successfully performed - */ - - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch(ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); - } - - - - - ChannelPromise finished = channel().newPromise(); - - //Every specified time frame by delay(), we perform the next action in our sequence - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - ChannelFuture channelFuture = actionHandler().apply(outboundMessage()); - - channelFuture.addListeners( - future -> actionHandler().resetFuture(), - future -> finished.setSuccess()); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - return finished; - } - - public abstract static class Builder, P extends ProbingAction> { - - public abstract B delay(Duration value); - - public abstract B outboundMessage(O value); - - public abstract B protocol(Protocol value); - - abstract P autoBuild(); - - public P build() { - P probingAction = autoBuild(); - probingAction.protocol().probingAction(probingAction); - return probingAction; - } - } - /** - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified - */ - static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } - -} - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java deleted file mode 100644 index eeecb468fce..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ /dev/null @@ -1,86 +0,0 @@ -// 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.monitoring.blackbox.handlers; - -import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.flogger.FluentLogger; - -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler.Sharable; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.SslProvider; -import java.security.cert.X509Certificate; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLParameters; - -/** - * Adds a client side SSL handler to the channel pipeline. - * - *

This must be the first handler provided for any handler provider list, if it is - * provided. The type parameter {@code C} is needed so that unit tests can construct this handler - * that works with {@link EmbeddedChannel}; - */ -@Singleton -@Sharable -public class SslClientInitializer extends ChannelInitializer { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - private final SslProvider sslProvider; - private final X509Certificate[] trustedCertificates; - - @Inject - public SslClientInitializer(SslProvider sslProvider) { - // null uses the system default trust store. - this(sslProvider, null); - } - - @VisibleForTesting - SslClientInitializer(SslProvider sslProvider, X509Certificate[] trustCertificates) { - logger.atInfo().log("Client SSL Provider: %s", sslProvider); - this.sslProvider = sslProvider; - this.trustedCertificates = trustCertificates; - } - - @Override - protected void initChannel(C channel) throws Exception { - Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - checkNotNull(protocol, "Protocol is not set for channel: %s", channel); - SslHandler sslHandler = - SslContextBuilder.forClient() - .sslProvider(sslProvider) - .trustManager(trustedCertificates) - .build() - .newHandler(channel.alloc(), protocol.host(), protocol.port()); - - // Enable hostname verification. - SSLEngine sslEngine = sslHandler.engine(); - SSLParameters sslParameters = sslEngine.getSSLParameters(); - sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); - sslEngine.setSSLParameters(sslParameters); - - channel.pipeline().addLast(sslHandler); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java deleted file mode 100644 index 1a1664a3c3c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2018 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.monitoring.blackbox.handlers; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import java.net.URL; -import javax.inject.Inject; - -public class WebWhoisActionHandler extends ActionHandler { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - @Inject - public WebWhoisActionHandler() {} - - @Override - public void channelRead0(ChannelHandlerContext ctx, HttpResponse response) throws Exception{ - if (response.status() == HttpResponseStatus.OK) { - logger.atInfo().log("Recieved Successful HttpResponseStatus"); - finished.setSuccess(); - System.out.println(response); - - } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { - - //Obtain url to be redirected to - URL url = new URL(response.headers().get("Location")); - - //From url, extract new host, port, and path - String newHost = url.getHost(); - String newPath = url.getPath(); - int newPort = url.getDefaultPort(); - - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); - - - Protocol oldProtocol = ctx.channel().attr(PROTOCOL_KEY).get(); - - //Build new Protocol from new attributes - ProbingAction currentAction = oldProtocol.probingAction(); - - //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort).toBuilder().build() - .host(newHost) - .path(newPath); - - //Modify HttpRequest sent to remote host to reflect new path and host - FullHttpRequest httpRequest = ((DefaultFullHttpRequest) currentAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); - - - //Create new probingAction that takes in the new Protocol and HttpRequest message - ProbingAction redirectedAction = currentAction., NewChannelAction>toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .build(); - - oldProtocol.probingAction(redirectedAction); - //close this channel as we no longer need it - ChannelFuture future = ctx.close(); - future.addListener( - f -> { - logger.atInfo().log("Successfully Closed Connection"); - - //Once channel is closed, establish new connection to redirected host, and repeat same actions - ChannelFuture secondFuture = redirectedAction.call(); - - //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - - } - ); - } else { - finished.setFailure(new RuntimeException()); - logger.atWarning().log(String.format("Received Response: %s", response.status())); - - } - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java deleted file mode 100644 index 01b93866b14..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java +++ /dev/null @@ -1,85 +0,0 @@ -// 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.monitoring.blackbox.Handlers; - -import static com.google.common.truth.Truth.assertThat; - -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelPromise; -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - - -/** Unit tests for {@link ActionHandler}. */ -@RunWith(JUnit4.class) -public class TestActionHandler { - - private final ActionHandler actionHandler = new ActionHandler(); - private EmbeddedChannel channel; - - @Before - public void setup() { - channel = new EmbeddedChannel(actionHandler); - } - - @Test - public void testHandler_Params() { - //initial check on Channel Activity - assertThat(channel.isActive()).isTrue(); - - - //Ensures channel Handler points to is right what - assertThat(actionHandler.getChannel()).isEqualTo(channel); - } - - @Test - public void testHandler_Behavior() { - //initial check on Channel Activity - assertThat(channel.isActive()).isTrue(); - - - ByteBuf outboundBuffer = Unpooled.copyInt(64); - - //Use ActionHandler's write method to check if the future returned is accurate - //and that it accurately writes out the inputBuffer - assertThat(actionHandler.apply(outboundBuffer)).isEqualTo(actionHandler.getFinished()); - assertThat(channel.outboundMessages().poll()).isEqualTo(outboundBuffer); - - //Creates Promise that is set to success when something changes on actionHandler's future - ChannelPromise testPromise = channel.newPromise(); - actionHandler.getFinished().addListener(f -> testPromise.setSuccess()); - - //Ensure that before reading inbound data, actionHandler's future stays inactive - assertThat(testPromise.isSuccess()).isFalse(); - - ByteBuf inputBuffer = Unpooled.copyInt(128); - - //Check that ActionHandler doesn't do anything to inbound Buffer - assertThat(channel.writeInbound(inputBuffer)).isFalse(); - - - //ensures that actionHandler's future's listener is active and that it is set to success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(actionHandler.getFinished().isSuccess()).isTrue(); - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java deleted file mode 100644 index 5d9a8b5a977..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ /dev/null @@ -1,147 +0,0 @@ -// 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.US_ASCII; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; -import io.netty.handler.codec.http.cookie.ClientCookieEncoder; -import io.netty.handler.codec.http.cookie.Cookie; -import io.netty.handler.codec.http.cookie.ServerCookieEncoder; - -/** Utility class for various helper methods used in testing. */ -public class TestUtils { - - public static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - - public static FullHttpRequest makeHttpGetRequest(String host, String path) { - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); - request.headers().set("host", host).setInt("content-length", 0); - return request; - } - - public static FullHttpResponse makeHttpResponse(String content, HttpResponseStatus status) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buf); - response.headers().setInt("content-length", buf.readableBytes()); - return response; - } - - public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status); - response.headers().setInt("content-length", 0); - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpRequest makeEppHttpRequest( - String content, - String host, - String path, - String accessToken, - String sslClientCertificateHash, - String clientAddress, - Cookie... cookies) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "application/epp+xml") - .set("accept", "application/epp+xml") - .set("X-SSL-Certificate", sslClientCertificateHash) - .set("X-Forwarded-For", clientAddress); - if (cookies.length != 0) { - request.headers().set("cookie", ClientCookieEncoder.STRICT.encode(cookies)); - } - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); - return response; - } - - public static FullHttpResponse makeEppHttpResponse( - String content, HttpResponseStatus status, Cookie... cookies) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "application/epp+xml"); - for (Cookie cookie : cookies) { - response.headers().add("set-cookie", ServerCookieEncoder.STRICT.encode(cookie)); - } - return response; - } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java deleted file mode 100644 index 399bc9c4c35..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright 2018 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.monitoring.blackbox.handlers; - -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.base.Throwables; -import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.ReferenceCountUtil; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import org.junit.rules.ExternalResource; - -/** - * Helper for setting up and testing client / server connection with netty. - * - *

Used in {@link SslClientInitializerTest} - */ -final class NettyRule extends ExternalResource { - - // All I/O operations are done inside the single thread within this event loop group, which is - // different from the main test thread. Therefore synchronizations are required to make sure that - // certain I/O activities are finished when assertions are performed. - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - - // Handler attached to server's channel to record the request received. - private EchoHandler echoHandler; - - // Handler attached to client's channel to record the response received. - private DumpHandler dumpHandler; - - private Channel channel; - - /** Sets up a server channel bound to the given local address. */ - void setUpServer(LocalAddress localAddress, ChannelHandler handler) { - checkState(echoHandler == null, "Can't call setUpServer twice"); - echoHandler = new EchoHandler(); - ChannelInitializer serverInitializer = - new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) { - // Add the given handler - ch.pipeline().addLast(handler); - // Add the "echoHandler" last to log the incoming message and send it back - ch.pipeline().addLast(echoHandler); - } - }; - ServerBootstrap sb = - new ServerBootstrap() - .group(eventLoopGroup) - .channel(LocalServerChannel.class) - .childHandler(serverInitializer); - ChannelFuture unusedFuture = sb.bind(localAddress).syncUninterruptibly(); - } - - /** Sets up a client channel connecting to the give local address. */ - void setUpClient( - LocalAddress localAddress, - Protocol protocol, - ChannelHandler handler) { - checkState(echoHandler != null, "Must call setUpServer before setUpClient"); - checkState(dumpHandler == null, "Can't call setUpClient twice"); - dumpHandler = new DumpHandler(); - ChannelInitializer clientInitializer = - new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) throws Exception { - // Add the given handler - ch.pipeline().addLast(handler); - // Add the "dumpHandler" last to log the incoming message - ch.pipeline().addLast(dumpHandler); - } - }; - Bootstrap b = - new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class) - .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol); - channel = b.connect(localAddress).syncUninterruptibly().channel(); - } - - void checkReady() { - checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); - } - - /** - * Test that a message can go through, both inbound and outbound. - * - *

The client writes the message to the server, which echos it back and saves the string in its - * promise. The client receives the echo and saves it in its promise. All these activities happens - * in the I/O thread, and this call itself returns immediately. - */ - void assertThatMessagesWork() throws Exception { - checkReady(); - assertThat(channel.isActive()).isTrue(); - - writeToChannelAndFlush(channel, "Hello, world!"); - assertThat(echoHandler.getRequestFuture().get()).isEqualTo("Hello, world!"); - assertThat(dumpHandler.getResponseFuture().get()).isEqualTo("Hello, world!"); - } - - Channel getChannel() { - checkReady(); - return channel; - } - - ThrowableSubject assertThatServerRootCause() { - checkReady(); - return assertThat( - Throwables.getRootCause( - assertThrows(ExecutionException.class, () -> echoHandler.getRequestFuture().get()))); - } - - ThrowableSubject assertThatClientRootCause() { - checkReady(); - return assertThat( - Throwables.getRootCause( - assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); - } - - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - private static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } - - /** A handler that dumps its inbound message to a promise that can be inspected later. */ - private static class DumpHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture responseFuture = new CompletableFuture<>(); - - Future getResponseFuture() { - return responseFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - // There is no more use of this message, we should release its reference count so that it - // can be more effectively garbage collected by Netty. - ReferenceCountUtil.release(msg); - // Save the string in the promise and make it as complete. - responseFuture.complete(response); - } - - /** Saves any inbound error into the failure cause of the promise. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); - } - } - - @Override - protected void after() { - Future unusedFuture = eventLoopGroup.shutdownGracefully(); - } - - private static void writeToChannelAndFlush(Channel channel, String data) { - ChannelFuture unusedFuture = - channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java deleted file mode 100644 index f7af491e39e..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -public class RedirectHandler { - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java deleted file mode 100644 index 6725643c48d..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ /dev/null @@ -1,205 +0,0 @@ -// 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.monitoring.blackbox.handlers; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; -import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; -import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SniHandler; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.SslProvider; -import io.netty.handler.ssl.util.SelfSignedCertificate; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.cert.CertPathBuilderException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import javax.net.ssl.SSLException; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; - -/** - * Unit tests for {@link SslClientInitializer}. - * - *

To validate that the handler accepts & rejects connections as expected, a test server and a - * test client are spun up, and both connect to the {@link LocalAddress} within the JVM. This avoids - * the overhead of routing traffic through the network layer, even if it were to go through - * loopback. It also alleviates the need to pick a free port to use. - * - *

The local addresses used in each test method must to be different, otherwise tests run in - * parallel may interfere with each other. - */ -@RunWith(Parameterized.class) -public class SslClientInitializerTest { - - /** Fake host to test if the SSL engine gets the correct peer host. */ - private static final String SSL_HOST = "www.example.tld"; - - /** Fake port to test if the SSL engine gets the correct peer port. */ - private static final int SSL_PORT = 12345; - - @Rule - public NettyRule nettyRule = new NettyRule(); - - @Parameter(0) - public SslProvider sslProvider; - - // We do our best effort to test all available SSL providers. - @Parameters(name = "{0}") - public static SslProvider[] data() { - return OpenSsl.isAvailable() - ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[] {SslProvider.JDK}; - } - - /** Saves the SNI hostname received by the server, if sent by the client. */ - private String sniHostReceived; - - /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .build() - .host(SSL_HOST); - - private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) - throws Exception { - SslContext sslContext = SslContextBuilder.forServer(privateKey, certificate).build(); - return new SniHandler( - hostname -> { - sniHostReceived = hostname; - return sslContext; - }); - } - - @Test - public void testSuccess_swappedInitializerWithSslHandler() throws Exception { - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider); - EmbeddedChannel channel = new EmbeddedChannel(); - channel.attr(PROTOCOL_KEY).set(PROTOCOL); - ChannelPipeline pipeline = channel.pipeline(); - pipeline.addLast(sslClientInitializer); - ChannelHandler firstHandler = pipeline.first(); - assertThat(firstHandler.getClass()).isEqualTo(SslHandler.class); - SslHandler sslHandler = (SslHandler) firstHandler; - assertThat(sslHandler.engine().getPeerHost()).isEqualTo(SSL_HOST); - assertThat(sslHandler.engine().getPeerPort()).isEqualTo(SSL_PORT); - assertThat(channel.isActive()).isTrue(); - } - - @Test - public void testSuccess_protocolAttributeNotSet() { - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider); - EmbeddedChannel channel = new EmbeddedChannel(); - ChannelPipeline pipeline = channel.pipeline(); - pipeline.addLast(sslClientInitializer); - // Channel initializer swallows error thrown, and closes the connection. - assertThat(channel.isActive()).isFalse(); - } - - @Test - public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Exception { - SelfSignedCertificate ssc = new SelfSignedCertificate(SSL_HOST); - LocalAddress localAddress = - new LocalAddress("DEFAULT_TRUST_MANAGER_REJECT_SELF_SIGNED_CERT_" + sslProvider); - nettyRule.setUpServer(localAddress, getServerHandler(ssc.key(), ssc.cert())); - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider); - nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); - // The connection is now terminated, both the client side and the server side should get - // exceptions. - nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); - nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); - assertThat(nettyRule.getChannel().isActive()).isFalse(); - } - - @Test - public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws Exception { - LocalAddress localAddress = - new LocalAddress("CUSTOM_TRUST_MANAGER_ACCEPT_CERT_SIGNED_BY_TRUSTED_CA_" + sslProvider); - - // Generate a new key pair. - KeyPair keyPair = getKeyPair(); - - // Generate a self signed certificate, and use it to sign the key pair. - SelfSignedCertificate ssc = new SelfSignedCertificate(); - X509Certificate cert = signKeyPair(ssc, keyPair, SSL_HOST); - - // Set up the server to use the signed cert and private key to perform handshake; - PrivateKey privateKey = keyPair.getPrivate(); - nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); - - // Set up the client to trust the self signed cert used to sign the cert that server provides. - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); - - setUpSslChannel(nettyRule.getChannel(), cert); - nettyRule.assertThatMessagesWork(); - - // Verify that the SNI extension is sent during handshake. - assertThat(sniHostReceived).isEqualTo(SSL_HOST); - } - - @Test - public void testFailure_customTrustManager_wrongHostnameInCertificate() throws Exception { - LocalAddress localAddress = - new LocalAddress("CUSTOM_TRUST_MANAGER_WRONG_HOSTNAME_" + sslProvider); - - // Generate a new key pair. - KeyPair keyPair = getKeyPair(); - - // Generate a self signed certificate, and use it to sign the key pair. - SelfSignedCertificate ssc = new SelfSignedCertificate(); - X509Certificate cert = signKeyPair(ssc, keyPair, "wrong.com"); - - // Set up the server to use the signed cert and private key to perform handshake; - PrivateKey privateKey = keyPair.getPrivate(); - nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); - - // Set up the client to trust the self signed cert used to sign the cert that server provides. - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); - - // When the client rejects the server cert due to wrong hostname, both the client and server - // should throw exceptions. - nettyRule.assertThatClientRootCause().isInstanceOf(CertificateException.class); - nettyRule.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST); - nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); - assertThat(nettyRule.getChannel().isActive()).isFalse(); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java deleted file mode 100644 index 7b4aae50106..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java +++ /dev/null @@ -1,94 +0,0 @@ -// 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.monitoring.blackbox.handlers; - -import static com.google.common.truth.Truth.assertThat; - -import io.netty.channel.Channel; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.util.SelfSignedCertificate; -import java.math.BigInteger; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.SecureRandom; -import java.security.Security; -import java.security.cert.X509Certificate; -import java.time.Duration; -import java.time.Instant; -import java.util.Date; -import javax.net.ssl.SSLSession; -import javax.security.auth.x500.X500Principal; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.x509.X509V3CertificateGenerator; - -/** - * Utility class that provides methods used by {@link SslClientInitializerTest} - */ -public class SslInitializerTestUtils { - - static { - Security.addProvider(new BouncyCastleProvider()); - } - - public static KeyPair getKeyPair() throws Exception { - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); - keyPairGenerator.initialize(2048, new SecureRandom()); - return keyPairGenerator.generateKeyPair(); - } - - /** - * Signs the given key pair with the given self signed certificate. - * - * @return signed public key (of the key pair) certificate - */ - public static X509Certificate signKeyPair( - SelfSignedCertificate ssc, KeyPair keyPair, String hostname) throws Exception { - X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); - X500Principal dnName = new X500Principal("CN=" + hostname); - certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); - certGen.setSubjectDN(dnName); - certGen.setIssuerDN(ssc.cert().getSubjectX500Principal()); - certGen.setNotBefore(Date.from(Instant.now().minus(Duration.ofDays(1)))); - certGen.setNotAfter(Date.from(Instant.now().plus(Duration.ofDays(1)))); - certGen.setPublicKey(keyPair.getPublic()); - certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); - return certGen.generate(ssc.key(), "BC"); - } - - /** - * Verifies tha the SSL channel is established as expected, and also sends a message to the server - * and verifies if it is echoed back correctly. - * - * @param certs The certificate that the server should provide. - * @return The SSL session in current channel, can be used for further validation. - */ - static SSLSession setUpSslChannel( - Channel channel, - X509Certificate... certs) - throws Exception { - SslHandler sslHandler = channel.pipeline().get(SslHandler.class); - // Wait till the handshake is complete. - sslHandler.handshakeFuture().get(); - - assertThat(channel.isActive()).isTrue(); - assertThat(sslHandler.handshakeFuture().isSuccess()).isTrue(); - assertThat(sslHandler.engine().getSession().isValid()).isTrue(); - assertThat(sslHandler.engine().getSession().getPeerCertificates()) - .asList() - .containsExactlyElementsIn(certs); - // Returns the SSL session for further assertion. - return sslHandler.engine().getSession(); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java deleted file mode 100644 index 001c935d70a..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ /dev/null @@ -1,208 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; - - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelPromise; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import org.joda.time.Duration; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ -@RunWith(JUnit4.class) -public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; - private static final int HTTPS_PORT = 443; - private static final String HTTP_REDIRECT = "http://"; - private static final String HTTPS_REDIRECT = "https://"; - private static final String REDIRECT_HOST = "www.example.com"; - private static final String REDIRECT_PATH = "/test/path"; - private static final String TARGET_HOST = "whois.nic.tld"; - private static final Duration DEFAULT_DURATION = new Duration(0L); - - - private EmbeddedChannel channel; - private ActionHandler actionHandler; - - /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { - return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); - } - - /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); - } - - /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); - } - - /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .build(); - } - - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); - } - - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - - @Test - public void testSuccess_responseOk() { - //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); - - //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); - - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that we successfully receivved good response and protocol is unchanged - assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); - } - - @Test - public void testSuccess_responseBad() { - //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); - - //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - - //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); - } - - @Test - public void testSuccess_redirectCloseChannel() { - //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); - - //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); - - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - - - channel.writeInbound(response); - - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - - - } - - @Test - public void testSuccess_redirectHost() { - //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - - //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - - - channel.writeInbound(originalResponse); - - //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - - - } - -} From dac2b1ba2ef4cb5d8de8cffe0745df9dd762a4c9 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 10 Jul 2019 17:34:38 -0400 Subject: [PATCH 013/337] Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle --- .../monitoring/blackbox/package-info.java | 15 --------------- .../monitoring/blackbox/package-info.java | 15 --------------- settings.gradle | 5 ++--- 3 files changed, 2 insertions(+), 33 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/package-info.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/package-info.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java deleted file mode 100644 index 21c8764701c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java +++ /dev/null @@ -1,15 +0,0 @@ -// 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.monitoring.blackbox; \ No newline at end of file diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java deleted file mode 100644 index 21c8764701c..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java +++ /dev/null @@ -1,15 +0,0 @@ -// 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.monitoring.blackbox; \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 0cd8f4dd707..eea358cfc0e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -30,11 +30,10 @@ rootProject.name = 'nomulus' include 'core' include 'prober' include 'proxy' -include 'third_party' -include 'util' include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' -include 'prober' +include 'third_party' +include 'util' From e0d8d392efd7293e16c01b89e4c0504edc4fcb36 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 10 Jul 2019 17:41:55 -0400 Subject: [PATCH 014/337] Fully Updated ActionHandler (missing updated JavaDoc) --- .../blackbox/handlers/ActionHandler.java | 58 +++++++------------ 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index a4df56408b5..c502f94015f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -15,72 +15,58 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import com.google.common.flogger.StackSize; -import io.netty.channel.ChannelInboundHandlerAdapter; +import google.registry.monitoring.blackbox.messages.InboundMarker; +import google.registry.monitoring.blackbox.messages.OutboundMarker; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpResponse; -import java.util.function.Function; -import javax.inject.Inject; /** * - * @param Generic Type of Inbound Message - * @param Generic Type of Outbound Message + * * Abstract class that tells sends message down pipeline and * and tells listeners to move on when the message is received. */ -public abstract class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); protected ChannelPromise finished; - private Channel channel; - + protected OutboundMarker outboundMessage; - /** returns ChannelPromise for when inbound message is recieved - * a - * @param outboundMessage - * @return - */ - @Override - public ChannelFuture apply(O outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline + /** Writes and flushes specified outboundMessage to channel pipeline and returns future + * that is marked as success when ActionHandler next reads from the channel */ + public ChannelFuture getFuture(OutboundMarker outboundMessage) { + //Action Handlers subclasses require the outboundMessage for additional logic + this.outboundMessage = outboundMessage; - channel.writeAndFlush(outboundMessage); + //returns the ChannelPromise initialized return finished; - - } - - public void resetFuture() { - finished = channel.newPromise(); } @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler - - channel = ctx.channel(); finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ - //Only purpose of Handler is to mark future as a success - + public void channelRead0(ChannelHandlerContext ctx, InboundMarker inboundMessage) throws Exception { + //simply marks finished as success finished.setSuccess(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); + logger.atSevere().withCause(cause).log(String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), + ctx.channel().pipeline().toString())); + + finished.setFailure(cause); + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } From 1d41ee65540d9a49fc2ecaea5cd2e39e927b58c9 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 10 Jul 2019 17:54:18 -0400 Subject: [PATCH 015/337] Added changed Protocol and both Inbound and Outbound Markers --- .../monitoring/blackbox/Protocol.java | 65 +++++-------------- .../blackbox/messages/InboundMarker.java | 22 +++++++ .../blackbox/messages/OutboundMarker.java | 21 ++++++ 3 files changed, 58 insertions(+), 50 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 913b7d7627e..8e39866cd56 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -16,6 +16,7 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; import javax.inject.Provider; @@ -29,7 +30,7 @@ public abstract class Protocol { public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); /** * Default names associated with each protocol */ @@ -38,77 +39,41 @@ public abstract class Protocol { final static String WHOIS_PROTOCOL_NAME = "WHOIS"; final static String RDAP_PROTOCOL_NAME = "RDAP"; - private String host; - private String path = ""; - private ProbingAction probingAction; - - /** Setter method for Protocol's host*/ - public Protocol host(String host) { - this.host = host; - return this; - } - - /** Getter method for Protocol's host*/ - public String host() { - return host; - } - - /** Setter method for Protocol's path*/ - public Protocol path(String path) { - this.path = path; - return this; - } - - /** Getter method for Protocol's path*/ - public String path() { - return path; - } - - /** Setter method for Protocol's ProbingAction parent*/ - public Protocol probingAction(ProbingAction probingAction) { - this.probingAction = probingAction; - return this; - } - - /** Getter method for Protocol's path*/ - public ProbingAction probingAction() { - return probingAction; - } - - /** If connection associated with Protocol is persistent, which is only EPP */ - public boolean persistentConnection() { - return name() == EPP_PROTOCOL_NAME; - } + /** Local Address of Protocol. ONLY FOR TESTING*/ + public abstract LocalAddress address(); /** Protocol Name */ - public abstract String name(); + abstract String name(); /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - public abstract ImmutableList> handlerProviders(); + abstract ImmutableList> handlerProviders(); + /** If connection associated with Protocol is persistent, which is only EPP */ + abstract boolean persistentConnection(); public abstract Builder toBuilder(); public static Builder builder() { - return new AutoValue_Protocol.Builder(); + return new AutoValue_Protocol.Builder().address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder { + public abstract Builder address(LocalAddress value); + public abstract Builder name(String value); public abstract Builder port(int num); public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder persistentConnection(boolean value); + public abstract Protocol build(); } - - - } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java new file mode 100644 index 00000000000..0a16344eb65 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java @@ -0,0 +1,22 @@ +// Copyright 2019 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.monitoring.blackbox.messages; + +/** + * Simple Interface that is implemented by all classes that serve + * as inboundMessages in the channel pipelines + */ +public interface InboundMarker {} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java new file mode 100644 index 00000000000..413a97ea0a0 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java @@ -0,0 +1,21 @@ +// Copyright 2019 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.monitoring.blackbox.messages; + +/** + * Simple Interface that is implemented by all classes that serve + * as outboundMessages in the channel pipelines + */ +public interface OutboundMarker {} From c932f8489368523dacfa80723ec9cb14c14f78ca Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 09:25:54 -0400 Subject: [PATCH 016/337] Removed AutoVaue ignore clause from .gitignore --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 199c4fe3979..327b22fe2e7 100644 --- a/.gitignore +++ b/.gitignore @@ -85,9 +85,6 @@ nomulus.iws # Javascript output **/out/* -# AutoValue generated code -AutoValue_.*.java - ###################################################################### # Python Ignores From 68c58ae596e2397496f357aca068dcdc33a1347c Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:23:33 -0400 Subject: [PATCH 017/337] removed unneccessary dependencies in build.gradle --- prober/build.gradle | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index e826fb6c37a..0f7931519b3 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,15 +1,25 @@ +// Copyright 2019 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. + apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] - compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] compile deps['io.netty:netty-buffer'] @@ -18,26 +28,16 @@ dependencies { compile deps['io.netty:netty-common'] compile deps['io.netty:netty-handler'] compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - //compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor annotationProcessor deps['com.google.auto.value:auto-value'] testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] -} \ No newline at end of file +} + From 48a2dd7eb4c8d3002d782b87b3c8ca1c1f23b0f9 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:47:39 -0400 Subject: [PATCH 018/337] Fixed Javadoc and comments for ActionHandler --- .../blackbox/handlers/ActionHandler.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index c502f94015f..814efd01e33 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -23,10 +23,16 @@ import io.netty.channel.ChannelPromise; /** + *Superclass of all Handlers placed at end of channel pipeline * + *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler}, as it should only be passed in + * messages that implement the {@link InboundMarker} interface.

* - * Abstract class that tells sends message down pipeline and - * and tells listeners to move on when the message is received. + *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMarker} + * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception + * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses + * specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -35,16 +41,16 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); } } - From 53de88316437d67a39e72f1c8b1c74e9de2eaf4f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:55:18 -0400 Subject: [PATCH 019/337] Fixed comments and JavaDoc on other files --- prober/build.gradle | 7 +++++++ .../monitoring/blackbox/Protocol.java | 19 +++---------------- .../blackbox/messages/InboundMarker.java | 3 +-- .../blackbox/messages/OutboundMarker.java | 3 +-- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 0f7931519b3..4590fe28148 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -20,6 +20,7 @@ dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] compile deps['io.netty:netty-buffer'] @@ -28,16 +29,22 @@ dependencies { compile deps['io.netty:netty-common'] compile deps['io.netty:netty-handler'] compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') // Include auto-value in compile until nebula-lint understands // annotationProcessor annotationProcessor deps['com.google.auto.value:auto-value'] testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 8e39866cd56..080acc30584 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -17,41 +17,29 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import io.netty.channel.local.LocalAddress; -import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; import javax.inject.Provider; /** - * Protocol Class packages all static variables necessary for a certain type of connection - * Both the host and the path can be changed for the same protocol - * Mainly packages the handlers necessary for the requisite channel pipeline + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection */ @AutoValue public abstract class Protocol { - public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** - * Default names associated with each protocol - */ - final static String EPP_PROTOCOL_NAME = "EPP"; - final static String DNS_PROTOCOL_NAME = "DNS"; - final static String WHOIS_PROTOCOL_NAME = "WHOIS"; - final static String RDAP_PROTOCOL_NAME = "RDAP"; /** Local Address of Protocol. ONLY FOR TESTING*/ public abstract LocalAddress address(); - /** Protocol Name */ abstract String name(); - /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ abstract ImmutableList> handlerProviders(); - /** If connection associated with Protocol is persistent, which is only EPP */ + /** Boolean that notes if connection associated with Protocol is persistent.*/ abstract boolean persistentConnection(); public abstract Builder toBuilder(); @@ -76,4 +64,3 @@ public static abstract class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java index 0a16344eb65..edd541f98f7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java @@ -15,8 +15,7 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve - * as inboundMessages in the channel pipelines + * Simple Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ public interface InboundMarker {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java index 413a97ea0a0..eb2c14e8096 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java @@ -15,7 +15,6 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve - * as outboundMessages in the channel pipelines + * Simple Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMarker {} From 74704f034bd15f365430848ddef304a1cde8b734 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:57:07 -0400 Subject: [PATCH 020/337] EOL added --- .../main/java/google/registry/monitoring/blackbox/Protocol.java | 1 + .../registry/monitoring/blackbox/handlers/ActionHandler.java | 1 + .../registry/monitoring/blackbox/messages/OutboundMarker.java | 1 + 3 files changed, 3 insertions(+) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 080acc30584..fa9f3814ddc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -64,3 +64,4 @@ public static abstract class Builder { public abstract Protocol build(); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 814efd01e33..c26882e5f4c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -76,3 +76,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java index eb2c14e8096..bd80aa0a062 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java @@ -18,3 +18,4 @@ * Simple Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMarker {} + From f1e65cbf270626fba94c6cb0614e4430441e3817 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 12 Jul 2019 12:10:20 -0400 Subject: [PATCH 021/337] Removed Unnecessary Files --- .../google/registry/monitoring/blackbox/ActionHandler.java | 5 ----- .../google/registry/monitoring/blackbox/ProbingAction.java | 5 ----- .../google/registry/monitoring/blackbox/ProbingSequence.java | 5 ----- .../google/registry/monitoring/blackbox/ProbingStep.java | 5 ----- .../java/google/registry/monitoring/blackbox/Protocol.java | 5 ----- .../java/google/registry/monitoring/blackbox/TestToken.java | 5 ----- .../main/java/google/registry/monitoring/blackbox/Token.java | 5 ----- 7 files changed, 35 deletions(-) delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java deleted file mode 100644 index a4d36657721..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ActionHandler { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java deleted file mode 100644 index 6b26913d425..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingAction { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java deleted file mode 100644 index 9f3617135a4..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingSequence { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java deleted file mode 100644 index b8b237a1e91..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingStep { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java deleted file mode 100644 index 75d13b3039a..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Protocol { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java deleted file mode 100644 index 98f21f8d63a..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class TestToken { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java deleted file mode 100644 index 16f05be0430..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Token { - -} From 7366c8e93e8d52c79968d050f813cc0db03cd450 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 12 Jul 2019 13:32:44 -0400 Subject: [PATCH 022/337] fixed .gradle files styles --- settings.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.gradle b/settings.gradle index eea358cfc0e..10ae29b66d1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -30,10 +30,10 @@ rootProject.name = 'nomulus' include 'core' include 'prober' include 'proxy' +include 'third_party' +include 'util' include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' -include 'third_party' -include 'util' From 44671db0b1ed702b3226946dcc322b8b7887142e Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 15:15:52 -0400 Subject: [PATCH 023/337] Removed outbound message from ActionHandler's fields and renamed Marker Interfaces --- .../blackbox/handlers/ActionHandler.java | 9 ++------ .../blackbox/messages/InboundMarker.java | 21 ------------------- .../blackbox/messages/InboundMessageType.java | 6 ++---- .../blackbox/messages/OutboundMarker.java | 21 ------------------- .../messages/OutboundMessageType.java | 20 ++---------------- 5 files changed, 6 insertions(+), 71 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index c26882e5f4c..22df091833d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -23,7 +23,7 @@ import io.netty.channel.ChannelPromise; /** - *Superclass of all Handlers placed at end of channel pipeline + *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler}, as it should only be passed in * messages that implement the {@link InboundMarker} interface.

@@ -39,14 +39,9 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler Date: Mon, 15 Jul 2019 15:17:40 -0400 Subject: [PATCH 024/337] Fixed javadoc for Marker Interfaced --- .../monitoring/blackbox/messages/InboundMessageType.java | 2 +- .../monitoring/blackbox/messages/OutboundMessageType.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 7f4b4135516..0c1260becf2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ public interface InboundMessageType {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index e1ed12f56d9..0dd17e9d4a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType {} From 8d0c196c70c7fce9da5040d511f2abbef56135b8 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 15:18:51 -0400 Subject: [PATCH 025/337] Modified Comments on ActionHandler --- .../blackbox/handlers/ActionHandler.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 22df091833d..dfd88cba1ce 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,8 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.messages.InboundMarker; -import google.registry.monitoring.blackbox.messages.OutboundMarker; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -25,22 +25,22 @@ /** *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler}, as it should only be passed in - * messages that implement the {@link InboundMarker} interface.

+ *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMarker} + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses * specify further work to be done for specific kinds of channel pipelines.

*/ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); protected ChannelPromise finished; - /** Takes in {@link OutboundMarker} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ public ChannelFuture getFuture() { return finished; } @@ -53,7 +53,7 @@ public void handlerAdded(ChannelHandlerContext ctx) { } @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMarker inboundMessage) throws Exception { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws Exception { //simply marks finished as success finished.setSuccess(); } From 3ae31b9beb93025672fd233d57d01a57529ac079 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 15:40:37 -0400 Subject: [PATCH 026/337] Removed LocalAddress from Protocol --- .../google/registry/monitoring/blackbox/Protocol.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index fa9f3814ddc..b0071ea4467 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,7 +16,6 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.local.LocalAddress; import io.netty.channel.ChannelHandler; import javax.inject.Provider; @@ -26,12 +25,6 @@ @AutoValue public abstract class Protocol { - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - - /** Local Address of Protocol. ONLY FOR TESTING*/ - public abstract LocalAddress address(); - abstract String name(); public abstract int port(); @@ -45,14 +38,12 @@ public abstract class Protocol { public abstract Builder toBuilder(); public static Builder builder() { - return new AutoValue_Protocol.Builder().address(DEFAULT_ADDRESS); + return new AutoValue_Protocol.Builder(); } @AutoValue.Builder public static abstract class Builder { - public abstract Builder address(LocalAddress value); - public abstract Builder name(String value); public abstract Builder port(int num); From ae8a07737b5cfa99a8cd572af50a1f0cf9cece32 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 16:13:43 -0400 Subject: [PATCH 027/337] Fixed Travis Build Issues --- prober/build.gradle | 5 ++--- settings.gradle | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 4590fe28148..e287bfd1bb9 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -18,7 +18,7 @@ createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober dependencies { def deps = rootProject.dependencyMap - + compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] @@ -34,7 +34,7 @@ dependencies { runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - + testCompile deps['com.google.truth:truth'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] @@ -47,4 +47,3 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } - diff --git a/settings.gradle b/settings.gradle index 10ae29b66d1..9b2d11de8da 100644 --- a/settings.gradle +++ b/settings.gradle @@ -36,4 +36,3 @@ include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' - From 32c186dd60ebe69571a40aaf5337e1db8db92dee Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 028/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 3 +- .../google/registry/xjc/package-info.java | 3 +- prober/build.gradle | 33 ++-- .../monitoring/blackbox/NewChannelAction.java | 136 +++++++++++++ .../registry/monitoring/blackbox/Prober.java | 23 +-- .../monitoring/blackbox/ProbingAction.java | 186 ++++++++++++++++++ .../handlers/ServerSideException.java | 15 ++ .../handlers/SslClientInitializer.java | 117 +++++++++++ .../handlers/WebWhoisActionHandler.java | 137 +++++++++++++ .../blackbox/messages/HttpRequestMessage.java | 70 +------ .../messages/HttpResponseMessage.java | 46 +++-- .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 15 files changed, 652 insertions(+), 125 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index ddff37c6807..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,3 +14,4 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.ui; + diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 5b5456585cc..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,3 +14,4 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.xjc; + diff --git a/prober/build.gradle b/prober/build.gradle index e287bfd1bb9..a277fb4f9f3 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -4,7 +4,7 @@ // 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 +// 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, @@ -12,12 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -apply plugin: 'java' - createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') dependencies { - def deps = rootProject.dependencyMap + def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.dagger:dagger'] @@ -30,20 +28,21 @@ dependencies { compile deps['io.netty:netty-handler'] compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] - runtime deps['com.google.flogger:flogger-system-backend'] - runtime deps['com.google.auto.value:auto-value'] - runtime deps['io.netty:netty-tcnative-boringssl-static'] + runtime deps['com.google.flogger:flogger-system-backend'] + runtime deps['com.google.auto.value:auto-value'] + runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') - // Include auto-value in compile until nebula-lint understands - // annotationProcessor - annotationProcessor deps['com.google.auto.value:auto-value'] - testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] + // Include auto-value in compile until nebula-lint understands + // annotationProcessor + annotationProcessor deps['com.google.auto.value:auto-value'] + testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..0ba3a0c22be --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 433d7361d5b..333330207f1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,30 +14,17 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by - * Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** - * Main Dagger Component - */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() - .build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java new file mode 100644 index 00000000000..2441debb12d --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -0,0 +1,186 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.flogger.StackSize.SMALL; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.util.AttributeKey; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; +import java.util.concurrent.Callable; +import javax.inject.Provider; + +/** + *Superclass that represents action generated by {@link ProbingStep} + * + *

Inherits from {@link Callable}, as it has can be called + * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the + * task has been completed

+ * + *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. + * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} + * gives the outline and {@link ProbingAction} gives the details of that connection.

+ * + *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ */ + + +public abstract class ProbingAction implements Callable { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; + + + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; + } + + /** {@link Timer} that rate limits probing */ + private static final Timer timer = new HashedWheelTimer(); + + + /** Actual {@link Duration} of this delay */ + public abstract Duration delay(); + + /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ + public abstract OutboundMessageType outboundMessage(); + + /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + public abstract Channel channel(); + + /** The {@link Protocol} instance that specifies type of connection */ + public abstract Protocol protocol(); + + public abstract String host(); + + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> finished.setSuccess(), + future -> { + if (!protocol().persistentConnection()) { + + //If we created a new channel for this action, close the connection to the channel + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** + * The method that sends the {@code outboundMessage} down the channel pipeline + * + * @return future that denotes when the action has been successfully performed + */ + + @Override + public ChannelFuture call() { + + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + } + + //ChannelPromise that we use to inform ProbingStep when we are finished. + ChannelPromise finished = channel().newPromise(); + + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } + + return finished; + } + + public abstract static class Builder, P extends ProbingAction> { + + public abstract B delay(Duration value); + + public abstract B outboundMessage(OutboundMessageType value); + + public abstract B protocol(Protocol value); + + public abstract B host(String value); + + public abstract B path(String value); + + public abstract P build(); + + } + + /** + * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified + * + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified + */ + static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); + } + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java new file mode 100644 index 00000000000..ac844ac99df --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -0,0 +1,117 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.base.Preconditions.checkNotNull; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.flogger.FluentLogger; + +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslProvider; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.function.Supplier; +import javax.inject.Singleton; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; + +/** + * Adds a client side SSL handler to the channel pipeline. + * + *

Code is close to unchanged from {@link SslClientInitializer}

in proxy, but is modified + * for revised overall structure of connections, and to accomdate EPP connections

+ * + *

This must be the first handler provided for any handler provider list, if it is + * provided. The type parameter {@code C} is needed so that unit tests can construct this handler + * that works with {@link EmbeddedChannel}; + */ +@Singleton +@Sharable +public class SslClientInitializer extends ChannelInitializer { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + private final SslProvider sslProvider; + private final X509Certificate[] trustedCertificates; + private final Supplier privateKeySupplier; + private final Supplier certificateSupplier; + + + public SslClientInitializer(SslProvider sslProvider) { + // null uses the system default trust store. + //Used for WebWhois, so we don't care about privateKey and certificates, setting them to null + this(sslProvider, null, null, null); + } + + public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, Supplier certificateSupplier) { + //We use the default trust store here as well, setting trustCertificates to null + this(sslProvider, null, privateKeySupplier, certificateSupplier); + } + + @VisibleForTesting + SslClientInitializer(SslProvider sslProvider, X509Certificate[] trustCertificates) { + this(sslProvider, trustCertificates, null, null); + } + + private SslClientInitializer( + SslProvider sslProvider, + X509Certificate[] trustCertificates, + Supplier privateKeySupplier, + Supplier certificateSupplier) { + logger.atInfo().log("Client SSL Provider: %s", sslProvider); + + this.sslProvider = sslProvider; + this.trustedCertificates = trustCertificates; + this.privateKeySupplier = privateKeySupplier; + this.certificateSupplier = certificateSupplier; + } + + @Override + protected void initChannel(C channel) throws Exception { + ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); + Protocol protocol = action.protocol(); + + //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate + checkNotNull(protocol, "Protocol is not set for channel: %s", channel); + SslContextBuilder sslContextBuilder = + SslContextBuilder.forClient() + .sslProvider(sslProvider) + .trustManager(trustedCertificates); + if (privateKeySupplier != null && certificateSupplier != null) + sslContextBuilder = sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get()); + + SslHandler sslHandler = sslContextBuilder + .build() + .newHandler(channel.alloc(), action.host(), protocol.port()); + + // Enable hostname verification. + SSLEngine sslEngine = sslHandler.engine(); + SSLParameters sslParameters = sslEngine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + sslEngine.setSSLParameters(sslParameters); + + channel.pipeline().addLast(sslHandler); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java new file mode 100644 index 00000000000..21010f0e887 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -0,0 +1,137 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; + +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; +import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpResponseStatus; +import java.net.MalformedURLException; +import java.net.URL; +import javax.inject.Inject; +import org.joda.time.Duration; + +/** + *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + * + *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection + * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

+ */ +public class WebWhoisActionHandler extends ActionHandler { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + @Inject + public WebWhoisActionHandler() {} + + + /** + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + */ + @Override + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) + throws ServerSideException { + + HttpResponseMessage response = (HttpResponseMessage) msg; + + + if (response.status() == HttpResponseStatus.OK) { + logger.atInfo().log("Received Successful HttpResponseStatus"); + + finished.setSuccess(); + + logger.atInfo().log("Response Received: " + response); + + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { + + //Obtain url to be redirected to + URL url; + try { + url = new URL(response.headers().get("Location")); + } catch (MalformedURLException e) { + //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it + throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + } + //From url, extract new host, port, and path + String newHost = url.getHost(); + String newPath = url.getPath(); + int newPort = url.getDefaultPort(); + + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); + + //Construct new Protocol to reflect redirected host, path, and port + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); + + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + + //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) + .build(); + + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + + //close this channel as we no longer need it + ChannelFuture future = ctx.close(); + future.addListener( + f -> { + logger.atInfo().log("Successfully Closed Connection"); + + //Once channel is closed, establish new connection to redirected host, and repeat same actions + ChannelFuture secondFuture = redirectedAction.call(); + + //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + secondFuture.addListener(f2 -> finished.setSuccess()); + + } + ); + } else { + //Add in metrics Handling that informs MetricsCollector the response was a FAILURE + finished.setSuccess(); + logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + + } + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b850cfb3b26..3fb8c187ad9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -19,40 +5,20 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import java.util.Arrays; -import javax.inject.Inject; -/** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. - * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a {@code - * name} method, which returns a standard name and the current hostname.

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, - ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } - /** - * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} - */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } @Override public HttpRequestMessage setUri(String path) { @@ -60,31 +26,15 @@ public HttpRequestMessage setUri(String path) { return this; } - /** - * Modifies headers to reflect new host and new path if applicable. - */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) { - setUri(args[1]); - } - - return this; + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + ByteBuf buf = request.content(); + if (buf == null) { + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - throw new IllegalArgumentException( - String.format( - "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of 2. Received arguments: " - + Arrays.toString(args), args.length)); + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - } - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 7d2ff722076..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,21 +6,33 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} - */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { + super(version, status); + } + + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } - /** - * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} - */ - public HttpResponseMessage(FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); + + return finalResponse; } + + + } diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From f6e0998e71e2fd432040b51af921b3889e973f18 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:58:52 -0400 Subject: [PATCH 029/337] Fixed changes suggested by CydeWeys --- .../google/registry/cron/package-info.java | 2 +- .../google/registry/xml/package-info.java | 2 +- prober/build.gradle | 28 +-- .../handlers/WebWhoisActionHandlerTest.java | 221 ++++++++++++++++++ 4 files changed, 238 insertions(+), 15 deletions(-) create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java diff --git a/core/src/main/java/google/registry/cron/package-info.java b/core/src/main/java/google/registry/cron/package-info.java index 459f2513f93..49b18ca2885 100644 --- a/core/src/main/java/google/registry/cron/package-info.java +++ b/core/src/main/java/google/registry/cron/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/core/src/main/java/google/registry/xml/package-info.java b/core/src/main/java/google/registry/xml/package-info.java index f8e42585ecc..b3f27868b91 100644 --- a/core/src/main/java/google/registry/xml/package-info.java +++ b/core/src/main/java/google/registry/xml/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/prober/build.gradle b/prober/build.gradle index a277fb4f9f3..dbb7252a462 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -4,7 +4,7 @@ // 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 +// 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, @@ -12,23 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +apply plugin: 'java' + createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') dependencies { def deps = rootProject.dependencyMap - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java new file mode 100644 index 00000000000..63bb2cf5b53 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -0,0 +1,221 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelPromise; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ +@RunWith(JUnit4.class) +public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; + private static final int HTTPS_PORT = 443; + private static final String HTTP_REDIRECT = "http://"; + private static final String HTTPS_REDIRECT = "https://"; + private static final String REDIRECT_HOST = "www.example.com"; + private static final String REDIRECT_PATH = "/test/path"; + private static final String TARGET_HOST = "whois.nic.tld"; + private static final Duration DEFAULT_DURATION = new Duration(0L); + + + private EmbeddedChannel channel; + private ActionHandler actionHandler; + + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { + return Protocol.builder() + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); + } + + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); + } + + /** Sets up testing channel with requisite attributes */ + private void setupChannel(Protocol protocol) { + setupActionHandler(); + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); + } + + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); + } + + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); + } + + + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; + } + + + @Test + public void testSuccess_responseOk() { + //setup + Protocol initialProtocol = createProtocol("responseOk", 0, ""); + setupChannel(initialProtocol); + + //stores future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that we successfully receivved good response and protocol is unchanged + assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + } + + @Test + public void testSuccess_responseBad() { + //setup + Protocol initialProtocol = createProtocol("responseBad", 0, ""); + setupChannel(initialProtocol); + + //stores future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, but event is not success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + + //ensures Protocol is the same + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + } + + @Test + public void testSuccess_redirectCloseChannel() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); + + //stores future + ChannelFuture future = actionHandler.apply(outboundMessage); + + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + + + } + + @Test + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + + + channel.writeInbound(originalResponse); + + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); + + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + + + } + +} From f7e7b7fadb8b1d6c162fe885138d115a74e6d4cf Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 030/337] Added missing license headers and JavaDoc --- .../handlers/ServerSideException.java | 16 ++++++- .../blackbox/messages/HttpRequestMessage.java | 45 ++++++++++++++----- .../messages/HttpResponseMessage.java | 32 ++++++++++--- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java index 5d3addb920e..441062a9e7b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; /** @@ -12,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 3fb8c187ad9..8fbb55c6339 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,13 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} + * (but needs to implement {@link OutboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion + * from {@link FullHttpRequest} to its type

+ */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +35,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,15 +42,22 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - if (buf == null) { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //creates message based on content found in original request + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //stores headers from request in finalRequest + request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); + + return finalRequest; + + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..776e7de0824 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,11 +1,33 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} + * (but needs to implement {@link InboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion + * from {@link FullHttpResponse} to its type

+ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -17,22 +39,20 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } + /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); + //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + //stores headers from response in finalResponse + response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); return finalResponse; } - - - } From f969b9390c04a4f835b7e55a41ffd0dc0f59f127 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 031/337] Minor fix in NewChannelAction JavaDoc --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..1e7578d5679 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; - import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -28,8 +27,7 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) */ @AutoValue public abstract class NewChannelAction extends ProbingAction { From 94a04c35d2b7a855872f73cd557dba4b72415a42 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 13:33:23 -0400 Subject: [PATCH 032/337] Minor Style Fix --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 ---- .../java/google/registry/monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/handlers/WebWhoisActionHandler.java | 2 -- 3 files changed, 7 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..84cf75492f2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -52,7 +52,6 @@ public Channel channel() { return this.channel; } - @Override public abstract Builder toBuilder(); @@ -120,7 +119,6 @@ public static NewChannelAction.Builder builder() return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -129,6 +127,4 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index b0071ea4467..2a4a8d0ed76 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -55,4 +55,3 @@ public static abstract class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 21010f0e887..5b77461cd8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -131,7 +131,5 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } } - - } From 2fb64b037957de0407b40ad2670cde62a6b59562 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 033/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 40 +-- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 17 +- .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProberModule.java | 101 ++++--- .../monitoring/blackbox/ProbingAction.java | 17 +- .../monitoring/blackbox/ProbingSequence.java | 122 +++++++++ .../monitoring/blackbox/ProbingStep.java | 170 ++++++++++++ .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 12 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 ++++ .../monitoring/blackbox/WebWhoisModule.java | 242 +++++++---------- .../exceptions/EppClientException.java | 29 ++ .../exceptions/InternalException.java | 29 ++ .../exceptions/ResponseException.java | 29 ++ .../ServerSideException.java | 4 +- .../blackbox/handlers/ActionHandler.java | 71 +++-- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/WebWhoisActionHandler.java | 19 +- .../handlers/WebWhoisMessageHandler.java | 42 +-- .../blackbox/messages/HttpRequestMessage.java | 50 +--- .../messages/HttpResponseMessage.java | 32 +-- .../blackbox/ProbingActionTest.java | 181 +++++++------ .../blackbox/ProbingSequenceStepTest.java | 219 +++++++++++++++ .../blackbox/TestServers/TestServer.java | 85 ++++++ .../blackbox/TestServers/WebWhoisServer.java | 92 +++++++ .../monitoring/blackbox/TestUtils.java | 252 ++++++++++++++++++ .../monitoring/blackbox/TokenTest.java | 60 +++++ .../blackbox/handlers/ConversionHandler.java | 23 +- .../blackbox/handlers/NettyRule.java | 201 ++++++++++++++ .../handlers/SslClientInitializerTest.java | 233 ++++++++++++++++ .../handlers/SslInitializerTestUtils.java | 95 +++++++ .../blackbox/handlers/TestActionHandler.java | 19 +- .../handlers/WebWhoisActionHandlerTest.java | 222 ++++++++++----- 36 files changed, 2457 insertions(+), 512 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java diff --git a/prober/build.gradle b/prober/build.gradle index dbb7252a462..993da44655d 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,30 +16,36 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') + //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -48,3 +54,5 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 84cf75492f2..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -52,6 +53,7 @@ public Channel channel() { return this.channel; } + @Override public abstract Builder toBuilder(); @@ -83,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -116,9 +118,10 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } + @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -127,4 +130,6 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } + } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 333330207f1..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,16 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index e5a71636173..73bd9127852 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,84 +14,99 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import io.netty.channel.Channel; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SslProvider; import java.util.Set; import javax.inject.Singleton; -import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and - * stores {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link - * ProbingSequence}. + * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} + * + *

Provides

*/ @Module public class ProberModule { + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; - /** - * Default {@link Duration} chosen to be time between each {@link ProbingAction} call. - */ - private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - - /** - * {@link Provides} the {@link SslProvider} used by instances of {@link - * google.registry.monitoring.blackbox.handlers.SslClientInitializer} - */ @Provides @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + EventLoopGroup provideEventLoopGroup() { + return new NioEventLoopGroup(); } - /** - * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. - */ @Provides - @Singleton - EventLoopGroup provideEventLoopGroup() { - return new NioEventLoopGroup(); + @HttpWhoisProtocol + ProbingSequence provideHttpWhoisSequence( + @HttpWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** - * {@link Provides} one global {@link Channel} class that is used to construct a {@link - * io.netty.bootstrap.Bootstrap}. - */ @Provides - @Singleton - Class provideChannelClazz() { - return NioSocketChannel.class; + @HttpsWhoisProtocol + ProbingSequence provideHttpsWhoisSequence( + @HttpsWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** - * {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. - */ @Provides - @Singleton - Duration provideDuration() { - return DEFAULT_DURATION; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } - /** - * Root level {@link Component} that provides each {@link ProbingSequence}. - */ + @Provides + @HttpsWhoisProtocol + int provideHttpsWhoisPort() { + return httpsWhoIsPort; + } + + @Provides + ImmutableMap providePortToProtocolMap( + Set protocolSet) { + return Maps.uniqueIndex(protocolSet, Protocol::port); + } + + + @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, + TokenModule.class }) public interface ProberComponent { - //Standard WebWhois sequence - Set sequences(); + @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); + + @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); + + ImmutableMap providePortToProtocolMap(); + + @WebWhoisProtocol Token provideWebWhoisToken(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2441debb12d..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -34,7 +34,7 @@ import javax.inject.Provider; /** - *Superclass that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -183,4 +183,19 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + @Override + public String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n" + + "path: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host(), + path() + ); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java new file mode 100644 index 00000000000..6387207fea4 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -0,0 +1,122 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.EventLoopGroup; + +/** + * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * + * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} + * but for tests is {@link LocalChannel} + * + *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, + * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * + *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one + * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ */ +public class ProbingSequence { + private ProbingStep firstStep; + + /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ + private EventLoopGroup eventGroup; + + /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ + private Bootstrap bootstrap; + + public Bootstrap getBootstrap() { + return bootstrap; + } + + public void start(Token token) { + // calls the first step with input token; + firstStep.accept(token); + } + + /** + * {@link Builder} which takes in {@link ProbingStep}s + * + * @param Same specified {@code C} for overall {@link ProbingSequence} + */ + public static class Builder { + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstSequenceStep; + private EventLoopGroup eventLoopGroup; + private Class classType; + + Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; + return this; + } + + Builder addStep(ProbingStep step) { + if (currentStep == null) { + firstStep = step; + } else { + currentStep.nextStep(step); + } + currentStep = step; + return this; + } + + /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ + Builder makeFirstRepeated() { + firstSequenceStep = currentStep; + return this; + } + /** Set the class to be the same as {@code C} */ + public Builder setClass(Class classType) { + this.classType = classType; + return this; + } + + public ProbingSequence build() { + currentStep.nextStep(firstSequenceStep); + currentStep.lastStep(); + return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + } + + } + + /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ + private void setParents() { + ProbingStep currentStep = firstStep.parent(this).nextStep(); + + while (currentStep != firstStep) { + currentStep = currentStep.parent(this).nextStep(); + } + } + private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, + Class classType) { + this.firstStep = firstStep; + this.eventGroup = eventLoopGroup; + this.bootstrap = new Bootstrap() + .group(eventGroup) + .channel(classType); + setParents(); + } + + @Override + public String toString() { + return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); + + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java new file mode 100644 index 00000000000..5bad5abf6bf --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -0,0 +1,170 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.io.IOException; +import java.util.function.Consumer; +import org.joda.time.Duration; + +/** + * Represents generator of actions performed at each step in {@link ProbingSequence} + * + * @param See {@code C} in {@link ProbingSequence} + * + *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are + * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies + * these components on each loop iteration with the consumed {@link Token} and from that, + * generates new {@link ProbingAction} to perform<./p> + * + *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

+ */ +public abstract class ProbingStep implements Consumer { + + public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); + protected static final Duration DEFAULT_DURATION = new Duration(2000L); + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + protected LocalAddress address = DEFAULT_ADDRESS; + + /** Necessary boolean to inform when to obtain next {@link Token}*/ + private boolean isLastStep = false; + private ProbingStep nextStep; + private ProbingSequence parent; + + protected Duration duration; + + protected final Protocol protocol; + protected final OutboundMessageType message; + + protected ProbingStep(Protocol protocol, OutboundMessageType message) { + this.protocol = protocol; + this.message = message; + } + + private OutboundMessageType message() { + return message; + } + + Protocol protocol() { + return protocol; + } + + + void lastStep() { + isLastStep = true; + } + + void nextStep(ProbingStep step) { + this.nextStep = step; + } + + ProbingStep nextStep() { + return this.nextStep; + } + + ProbingStep parent(ProbingSequence parent) { + this.parent = parent; + return this; + } + + /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + private ProbingAction generateAction(Token token) throws InternalException { + ProbingAction generatedAction; + + OutboundMessageType message = token.modifyMessage(message()); + + //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction + if (protocol().persistentConnection() && token.channel() != null) { + generatedAction = ExistingChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .channel(token.channel()) + .build(); + } else { + generatedAction = NewChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .bootstrap(parent.getBootstrap()) + .address(address) + .build(); + + } + return generatedAction; + } + + + /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + private Token generateNextToken(Token token) { + return (isLastStep) ? token.next() : token; + } + + @Override + public void accept(Token token) { + ProbingAction nextAction; + //attempt to generate new action. On error, move on to next step + try { + nextAction = generateAction(token); + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Generation"); + nextStep.accept(generateNextToken(token)); + return; + } + + //If the next step maintains the connection, pass on the channel from this + if (protocol().persistentConnection()) { + token.channel(nextAction.channel()); + } + + //call the created action + ChannelFuture future = nextAction.call(); + + //On result, either log success and move on, or + future.addListener(f -> { + if (f.isSuccess()) { + logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); + nextStep.accept(generateNextToken(token)); + } else { + logger.atSevere().withCause(f.cause()).log("Did not result in future success"); + } + }); + } + + @Override + public String toString() { + return String.format("ProbingStep with Protocol: %s\n" + + "OutboundMessage: %s\n" + + "and parent sequence: %s", + protocol(), + message(), + parent); + } + +} + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 2a4a8d0ed76..855d9c5b41a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -54,4 +54,16 @@ public static abstract class Builder { public abstract Protocol build(); } + + @Override + public String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 8365607da40..dba905c0e49 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,61 +18,61 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; + +import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.time.Duration; -/** - * A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. - */ +/** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - private static final String HTTP_PROTOCOL_NAME = "http"; - private static final String HTTPS_PROTOCOL_NAME = "https"; - /** - * Standard length of messages used by Proxy. Equates to 0.5 MB. - */ - private static final int maximumMessageLengthBytes = 512 * 1024; - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; - - /** - * {@link Provides} only step used in WebWhois sequence. - */ + final static String DOMAIN_SUFFIX = "whois.nic."; + + + /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ + @Qualifier + @interface HttpWhoisProtocol {} + + /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ + @Qualifier + @interface HttpsWhoisProtocol {} + + /** Dagger qualifier to provide any WebWhois related bindings. */ + @Qualifier + public @interface WebWhoisProtocol {} + + + + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + + @Provides - @WebWhoisProtocol - static ProbingStep provideWebWhoisStep( - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @WebWhoisProtocol Bootstrap bootstrap, - HttpRequestMessage messageTemplate, - Duration duration) { - - return ProbingStep.builder() - .setProtocol(httpWhoisProtocol) - .setBootstrap(bootstrap) - .setMessageTemplate(messageTemplate) - .setDuration(duration) - .build(); + @HttpWhoisProtocol + static ProbingStep provideHttpWhoisProbingSequence( + @HttpWhoisProtocol Protocol httpWhoisProtocol) { + return new ProbingStepWeb<>(httpWhoisProtocol); + } + + @Provides + @HttpsWhoisProtocol + static ProbingStep provideHttpsWhoisProbingStep( + @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { + return new ProbingStepWeb<>(httpsWhoisProtocol); } - /** - * {@link Provides} the {@link Protocol} that corresponds to http connection. - */ + @Singleton @Provides @HttpWhoisProtocol @@ -80,16 +80,28 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTP_PROTOCOL_NAME) - .setPort(httpWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** - * {@link Provides} the {@link Protocol} that corresponds to https connection. - */ + @Singleton + @Provides + @IntoSet + static Protocol provideHttpProtocolForSet( + @HttpWhoisProtocol int httpWhoisPort, + @HttpWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Singleton @Provides @HttpsWhoisProtocol @@ -97,23 +109,40 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTPS_PROTOCOL_NAME) - .setPort(httpsWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** - * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http - * protocol. - */ + @Singleton + @Provides + @IntoSet + static Protocol provideHttpsProtocolForSet( + @HttpsWhoisProtocol int httpsWhoisPort, + @HttpsWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Provides + @WebWhoisProtocol + String provideHttpWhoisHost() { + return "app"; + } + + @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -122,18 +151,13 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** - * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https - * protocol. - */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( - @HttpsWhoisProtocol - Provider> sslClientInitializerProvider, + @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -143,106 +167,34 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } - @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); - } - - @Provides - static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { - return new HttpObjectAggregator(maxContentLength); - } - - /** - * {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. - */ - @Provides - @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer( - SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); - } - /** - * {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. - */ - @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap( - EventLoopGroup eventLoopGroup, - Class channelClazz) { - return new Bootstrap() - .group(eventLoopGroup) - .channel(channelClazz); + static MessageHandler provideMessageHandler() { + return new WebWhoisMessageHandler(); } - /** - * {@link Provides} standard WebWhois sequence. - */ @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { - - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); - } - - @Provides - @WebWhoisProtocol - int provideMaximumMessageLengthBytes() { - return maximumMessageLengthBytes; + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); } - /** - * {@link Provides} the list of top level domains to be probed - */ - @Singleton @Provides - @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy", "xn--q9jyb4c"); + static HttpObjectAggregator provideHttpObjectAggregator() { + return new HttpObjectAggregator(1048576); } @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return HTTP_WHOIS_PORT; + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } @Provides @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return HTTPS_WHOIS_PORT; - } - - /** - * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. - */ - @Qualifier - public @interface HttpWhoisProtocol { - - } - - /** - * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. - */ - @Qualifier - public @interface HttpsWhoisProtocol { - - } - - /** - * Dagger qualifier to provide any WebWhois related bindings. - */ - @Qualifier - public @interface WebWhoisProtocol { - + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index dfd88cba1ce..c3622e1b810 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,32 +15,45 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; /** - *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + * Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, + * as it should only be passed in messages that implement the {@link InboundMessageType} interface. * - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} - * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception - * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses - * specify further work to be done for specific kinds of channel pipelines.

+ *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link + * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. + * Second, it stores the {@link OutboundMessageType} passed down the pipeline, so that subclasses + * can use that information for their own processes. Lastly, with any exception thrown, the + * connection is closed, and the ProbingAction governing this channel is informed of the error. + * Subclasses specify further work to be done for specific kinds of channel pipelines. */ public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Three types of responses received down pipeline */ + public enum ResponseType {SUCCESS, FAILURE, ERROR} + + /** Status of response for current {@link ActionHandler} instance */ + private static ResponseType status; + protected ChannelPromise finished; - /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** + * Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized + * {@link ChannelPromise} + */ public ChannelFuture getFuture() { return finished; } @@ -48,25 +61,47 @@ public ChannelFuture getFuture() { /** Initializes new {@link ChannelPromise} */ @Override public void handlerAdded(ChannelHandlerContext ctx) { - //Once handler is added to channel pipeline, initialize channel and future for this handler + // Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws Exception { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { //simply marks finished as success + status = ResponseType.SUCCESS; finished.setSuccess(); } - /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ + /** + * Logs the channel and pipeline that caused error, closes channel, then informs {@link + * ProbingAction} listeners of error + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); + logger.atSevere().withCause(cause).log( + String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), ctx.channel().pipeline().toString())); + + + if (ResponseException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + status = ResponseType.FAILURE; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (ServerSideException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + status = ResponseType.ERROR; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (InternalException.class.isInstance(cause)){ + logger.atSevere().withCause(cause).log("Severe internal error"); + finished.setFailure(cause); + } else { + finished.setFailure(cause); + } - finished.setFailure(cause); + //due to failure, close channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 5b77461cd8f..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -17,20 +17,16 @@ import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; @@ -59,7 +55,7 @@ public WebWhoisActionHandler() {} */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ServerSideException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -67,9 +63,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - finished.setSuccess(); - logger.atInfo().log("Response Received: " + response); + super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -79,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -126,10 +121,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + throw new ResponseException("Response received from remote site was: " + response.status()); } } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 576d6a04d42..4afc5d95ba7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,59 +1,33 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -/** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom - * type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for - * redirection. - */ -public class WebWhoisMessageHandler extends ChannelDuplexHandler { +public class WebWhoisMessageHandler extends MessageHandler { + + private HttpRequestMessage request; @Inject - public WebWhoisMessageHandler() { - } + public WebWhoisMessageHandler() {} - /** - * Retains {@link HttpRequestMessage} and calls super write method. - */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) - throws Exception { - HttpRequestMessage request = (HttpRequestMessage) msg; + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** - * Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link - * InboundMessageType} instance. - */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + FullHttpResponse originalResponse = (FullHttpResponse) msg; - HttpResponseMessage response = new HttpResponseMessage(originalResponse); + InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8fbb55c6339..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,13 +6,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} - * (but needs to implement {@link OutboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion - * from {@link FullHttpRequest} to its type

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -35,6 +14,11 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + + @Override public HttpRequestMessage setUri(String path) { @@ -42,22 +26,16 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - - //creates message based on content found in original request - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - - - //stores headers from request in finalRequest - request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - - return finalRequest; - + HttpRequestMessage output; + if (buf == null) { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + } else { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + } + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 776e7de0824..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,33 +1,11 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} - * (but needs to implement {@link InboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion - * from {@link FullHttpResponse} to its type

- */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -39,20 +17,22 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } - /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); - //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - //stores headers from response in finalResponse - response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); return finalResponse; } + + + } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index df3296438af..cbcf2fc82b0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,102 +15,135 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import javax.inject.Provider; import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; - /** * Unit tests for {@link ProbingAction} subtypes * *

Attempts to test how well each {@link ProbingAction} works with an {@link ActionHandler} * subtype when receiving to all possible types of responses

- */ + * */ @RunWith(JUnit4.class) public class ProbingActionTest { + /** Necessary Constants for test */ + private final String TEST_MESSAGE = "MESSAGE_TEST"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final int TEST_PORT = 0; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - private static final String TEST_MESSAGE = "MESSAGE_TEST"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final int TEST_PORT = 0; + private ProbingAction newChannelAction; + private ProbingAction existingChannelAction; + private EmbeddedChannel channel; + private Protocol protocol; - private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - /** - * Used for testing how well probing step can create connection to blackbox server - */ + /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** - * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on - * {@link ProbingAction} - */ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - //TODO - Currently, this test fails to receive outbound messages from the embedded channel, which - // we will fix in a later release. - @Ignore - @Test - public void testSuccess_existingChannel() { - //setup - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up a Protocol corresponding to when a connection exists. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(true) + /** Sets up a {@link Protocol} corresponding to when a new connection is created */ + private void setupNewChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(false) + .build(); + } + /** Sets up a {@link Protocol} corresponding to when a new connection exists */ + private void setupExistingChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(true) .build(); + } - // Sets up a ProbingAction that creates a channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setChannel(channel) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost("") + /** Sets up a {@link NewChannelAction} with test specified attributes */ + private void setupNewChannelAction() { + newChannelAction = NewChannelAction.builder() + .bootstrap(bootstrap) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .address(address) .build(); + } - //tests main function of ProbingAction - ChannelFuture future = action.call(); + private void setupChannel() { + channel = new EmbeddedChannel(); + } - //Obtains the outboundMessage passed through pipeline after delay - Object msg = null; - while (msg == null) { - msg = channel.readOutbound(); - } - //tests the passed message is exactly what we expect - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - assertThat(request).isEqualTo(TEST_MESSAGE); + /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + private void setupExistingChannelAction(Channel channel) { + existingChannelAction = ExistingChannelAction.builder() + .channel(channel) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .build(); + } + + @Test + public void testBehavior_existingChannel() { + //setup + setupChannel(); + setupExistingChannelProtocol(); + setupExistingChannelAction(channel); + channel.pipeline().addLast(conversionHandler); + channel.pipeline().addLast(testHandler); + + + ChannelFuture future = existingChannelAction.call(); - // Ensures that we haven't marked future as done until response is received. - assertThat(future.isDone()).isFalse(); + //Ensures that we pass in the right message to the channel and haven't marked the future as success yet + Object msg = channel.readOutbound(); + assertThat(msg).isInstanceOf(ByteBuf.class); + String response = ((ByteBuf) msg).toString(UTF_8); + assertThat(response).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()).isFalse(); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); @@ -122,41 +155,19 @@ public void testSuccess_existingChannel() { @Test public void testSuccess_newChannel() throws Exception { //setup + setupNewChannelProtocol(); + setupNewChannelAction(); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - LocalAddress address = new LocalAddress(ADDRESS_NAME); - Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); - - // Sets up a Protocol corresponding to when a new connection is created. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - - nettyRule.setUpServer(address); - - // Sets up a ProbingAction with existing channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future = future.syncUninterruptibly(); + future.sync(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler) testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()); + assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java new file mode 100644 index 00000000000..7a713017072 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java @@ -0,0 +1,219 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.TestUtils.TestStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.handlers.ConversionHandler; +import google.registry.monitoring.blackbox.handlers.NettyRule; +import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.junit.Rule; +import org.junit.Test; + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + + /** Used for testing how well probing step can create connection to blackbox server */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + + + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ + private ProbingSequence testSequence; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); + dummyStep = new DummyStep(testProtocol, eventLoopGroup); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(false) + .build(); + } + + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(true) + .build(); + } + + /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ + private void setupSequence() { + testSequence = new ProbingSequence.Builder() + .eventLoopGroup(eventLoopGroup) + .setClass(LocalChannel.class) + .addStep(firstStep) + .makeFirstRepeated() + .addStep(dummyStep) + .build(); + } + + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //there should be no next step + assertThat(firstStep.nextStep()).isNull(); + + //we expect that this exception be thrown + assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); + + } + + @Test + public void testWithSequence_NewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupSequence(); + setupNewChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupSequence(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java new file mode 100644 index 00000000000..67e2cb7165d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -0,0 +1,85 @@ +package google.registry.monitoring.blackbox.TestServers; + +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; + +/** + * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + */ +public abstract class TestServer { + private LocalAddress localAddress; + + TestServer(LocalAddress localAddress, ImmutableList handlers) { + this(new NioEventLoopGroup(1), localAddress, handlers); + } + + TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + this.localAddress = localAddress; + + //Creates ChannelInitializer with handlers specified + ChannelInitializer serverInitializer = new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) { + for (ChannelHandler handler : handlers) { + ch.pipeline().addLast(handler); + } + } + }; + //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using LocalServerChannel class + ServerBootstrap serverBootstrap = + new ServerBootstrap() + .group(eventLoopGroup) + .channel(LocalServerChannel.class) + .childHandler(serverInitializer); + + ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); + + } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** Saves any inbound error as the cause of the promise failure. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java new file mode 100644 index 00000000000..ab9997b6c68 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -0,0 +1,92 @@ +package google.registry.monitoring.blackbox.TestServers; + +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpServerCodec; + +/** + * {@link TestServer} subtype that performs WebWhois Services Expected + * + * It will either redirect the client to the correct location if given the + * requisite redirect input, give the client a successful response if they give + * the expected final destination, or give the client an error message if given + * an unexpected host location + */ +public class WebWhoisServer extends TestServer { + + public WebWhoisServer(LocalAddress localAddress, ImmutableList handlers) { + super(localAddress, handlers); + } + + public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + super(eventLoopGroup, localAddress, handlers); + } + + /** Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the HttpRequestMessage object through pipeline */ + public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + return new WebWhoisServer( + eventLoopGroup, + localAddress, + ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) + ); + } + /** Creates server that sends exactly what we expect a remote server to send as a response, by sending the {@link ByteBuf} of the response through pipeline */ + public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + return new WebWhoisServer( + eventLoopGroup, + localAddress, + ImmutableList.of( + new HttpServerCodec(), + new HttpObjectAggregator(1048576), + new RedirectHandler(redirectInput, destinationInput)) + ); + } + + /** + * Handler that will wither redirect client, give successful response, or give error messge + */ + @Sharable + static class RedirectHandler extends ChannelDuplexHandler { + private String redirectInput; + private String destinationInput; + + /** + * + * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + */ + public RedirectHandler(String redirectInput, String destinationInput) { + this.redirectInput = redirectInput; + this.destinationInput = destinationInput; + } + + /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + HttpRequest request = (HttpRequest) msg; + HttpResponse response; + if (request.headers().get("host").equals(redirectInput)) { + response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + } else if (request.headers().get("host").equals(destinationInput)) { + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + } else { + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + } + ctx.channel().writeAndFlush(response); + + } + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java new file mode 100644 index 00000000000..8d1722c9625 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -0,0 +1,252 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.US_ASCII; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.joda.time.Duration; + +/** Utility class for various helper methods used in testing. */ +public class TestUtils { + + static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + + public static FullHttpRequest makeHttpGetRequest(String host, String path) { + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); + request.headers().set("host", host).setInt("content-length", 0); + return request; + } + + public static FullHttpResponse makeHttpResponse(String content, HttpResponseStatus status) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buf); + response.headers().setInt("content-length", buf.readableBytes()); + return response; + } + + public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status); + response.headers().setInt("content-length", 0); + return response; + } + + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + public static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; + } + + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); + return response; + } + + /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ + public static class TestProvider implements Provider { + + private E obj; + + public TestProvider(E obj) { + this.obj = obj; + } + + @Override + public E get() { + return obj; + } + } + + /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ + public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { + + String message; + + public DuplexMessageTest() { + message = ""; + } + + public DuplexMessageTest(String msg) { + message = msg; + } + + @Override + public String toString() { + return message; + } + } + + /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ + public static class TestStep extends ProbingStep { + + public TestStep(Protocol protocol, String testMessage, LocalAddress address) { + super(protocol, new DuplexMessageTest(testMessage)); + this.address = address; + this.duration = Duration.ZERO; + } + } + + /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ + public static class DummyStep extends ProbingStep { + private DefaultPromise future; + + public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { + super(protocol, new DuplexMessageTest()); + future = new DefaultPromise(eventLoopGroup.next()) {}; + duration = Duration.ZERO; + } + + @Override + public void accept(Token token) { + future.setSuccess(token); + } + public DefaultPromise getFuture() { + return future; + } + } + + /** Basic outline for {@link Token} instances to be used in tests */ + private static abstract class TestToken extends Token { + private String host; + + protected TestToken(String host) { + this.host = host; + } + @Override + public Token next() { + return this; + } + + @Override + public OutboundMessageType modifyMessage(OutboundMessageType message) { + return message; + } + + @Override + public String getHost() { + return host; + } + + } + + /** {@link TestToken} instance that creates new channel */ + public static class NewChannelToken extends TestToken { + public NewChannelToken(String host) { + super(host); + } + @Override + public Channel channel() { + return null; + } + } + + /** {@link TestToken} instance that passes in existing channel */ + public static class ExistingChannelToken extends TestToken { + private Channel channel; + + public ExistingChannelToken(Channel channel, String host) { + super(host); + this.channel = channel; + } + @Override + public Channel channel() { + return channel; + } + } + + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java new file mode 100644 index 00000000000..ef5cba5b60d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -0,0 +1,60 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + */ +@RunWith(JUnit4.class) +public class TokenTest { + + private static String PREFIX = "whois.nic."; + private static String TEST_STARTER = "starter"; + private static String TEST_DOMAIN = "test"; + + public Token webToken = new WebWhoisToken(TEST_DOMAIN); + + @Test + public void testWebToken_MessageModificationSuccess() { + //creates Request message with header + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + message.headers().set("host", TEST_STARTER); + + //attempts to use Token's method for modifying the method based on its stored host + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { + throw new RuntimeException(e); + } + + + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 987abbfd7dc..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,38 +17,31 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link - * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to + * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** - * Handles inbound conversion - */ + /** Handles inbound conversion */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } - /** - * Handles outbound conversion - */ + /** Handles outbound conversion */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java new file mode 100644 index 00000000000..b6b5e8fbe0c --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -0,0 +1,201 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.truth.Truth.assertThat; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.truth.ThrowableSubject; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.ReferenceCountUtil; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import org.junit.rules.ExternalResource; + +/** + * Helper for setting up and testing client / server connection with netty. + * + *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ */ +public final class NettyRule extends ExternalResource { + + + + // All I/O operations are done inside the single thread within this event loop group, which is + // different from the main test thread. Therefore synchronizations are required to make sure that + // certain I/O activities are finished when assertions are performed. + public NettyRule() { + eventLoopGroup = new NioEventLoopGroup(1); + } + public NettyRule(EventLoopGroup e) { + eventLoopGroup = e; + } + private final EventLoopGroup eventLoopGroup; + private WebWhoisServer webWhoisServer; + + // Handler attached to server's channel to record the request received. + private EchoHandler echoHandler; + + // Handler attached to client's channel to record the response received. + private DumpHandler dumpHandler; + + private Channel channel; + + /** Sets up a server channel bound to the given local address. */ + public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + checkState(echoHandler == null, "Can't call setUpServer twice"); + echoHandler = new EchoHandler(); + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + } + + /** Sets up a client channel connecting to the give local address. */ + void setUpClient( + LocalAddress localAddress, + ProbingAction probingAction, + ChannelHandler handler) { + checkState(echoHandler != null, "Must call setUpServer before setUpClient"); + checkState(dumpHandler == null, "Can't call setUpClient twice"); + dumpHandler = new DumpHandler(); + ChannelInitializer clientInitializer = + new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) throws Exception { + // Add the given handler + ch.pipeline().addLast(handler); + // Add the "dumpHandler" last to log the incoming message + ch.pipeline().addLast(dumpHandler); + } + }; + Bootstrap b = + new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class) + .handler(clientInitializer) + .attr(PROBING_ACTION_KEY, probingAction); + channel = b.connect(localAddress).syncUninterruptibly().channel(); + } + + private void checkReady() { + checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); + } + + /** Test that custom setup to send message to current server sends right message */ + public void assertThatCustomWorks(String message) throws Exception { + assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); + + } + + /** + * Test that a message can go through, both inbound and outbound. + * + *

The client writes the message to the server, which echos it back and saves the string in its + * promise. The client receives the echo and saves it in its promise. All these activities happens + * in the I/O thread, and this call itself returns immediately. + */ + void assertThatMessagesWork() throws Exception { + checkReady(); + assertThat(channel.isActive()).isTrue(); + + writeToChannelAndFlush(channel, "Hello, world!"); + assertThat(echoHandler.getRequestFuture().get()).isEqualTo("Hello, world!"); + assertThat(dumpHandler.getResponseFuture().get()).isEqualTo("Hello, world!"); + } + + Channel getChannel() { + checkReady(); + return channel; + } + + ThrowableSubject assertThatServerRootCause() { + checkReady(); + return assertThat( + Throwables.getRootCause( + assertThrows(ExecutionException.class, () -> echoHandler.getRequestFuture().get()))); + } + + ThrowableSubject assertThatClientRootCause() { + checkReady(); + return assertThat( + Throwables.getRootCause( + assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); + } + + + + /** A handler that dumps its inbound message to a promise that can be inspected later. */ + private static class DumpHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture responseFuture = new CompletableFuture<>(); + + Future getResponseFuture() { + return responseFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + assertThat(msg).isInstanceOf(ByteBuf.class); + String response = ((ByteBuf) msg).toString(UTF_8); + // There is no more use of this message, we should release its reference count so that it + // can be more effectively garbage collected by Netty. + ReferenceCountUtil.release(msg); + // Save the string in the promise and make it as complete. + responseFuture.complete(response); + } + + /** Saves any inbound error into the failure cause of the promise. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); + } + } + + @Override + protected void after() { + Future unusedFuture = eventLoopGroup.shutdownGracefully(); + } + + private static void writeToChannelAndFlush(Channel channel, String data) { + ChannelFuture unusedFuture = + channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java new file mode 100644 index 00000000000..469c62a8f75 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -0,0 +1,233 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; +import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; +import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.ExistingChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SniHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslProvider; +import io.netty.handler.ssl.util.SelfSignedCertificate; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.cert.CertPathBuilderException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLException; +import org.joda.time.Duration; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +/** + * Unit tests for {@link SslClientInitializer}. + * + *

To validate that the handler accepts & rejects connections as expected, a test server and a + * test client are spun up, and both connect to the {@link LocalAddress} within the JVM. This avoids + * the overhead of routing traffic through the network layer, even if it were to go through + * loopback. It also alleviates the need to pick a free port to use. + * + *

The local addresses used in each test method must to be different, otherwise tests run in + * parallel may interfere with each other. + */ +@RunWith(Parameterized.class) +public class SslClientInitializerTest { + + private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); + + /** Fake host to test if the SSL engine gets the correct peer host. */ + private static final String SSL_HOST = "www.example.tld"; + + /** Fake port to test if the SSL engine gets the correct peer port. */ + private static final int SSL_PORT = 12345; + + @Rule + public NettyRule nettyRule = new NettyRule(); + + @Parameter(0) + public SslProvider sslProvider; + + // We do our best effort to test all available SSL providers. + @Parameters(name = "{0}") + public static SslProvider[] data() { + return OpenSsl.isAvailable() + ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[] {SslProvider.JDK}; + } + + /** Saves the SNI hostname received by the server, if sent by the client. */ + private String sniHostReceived; + + /** Fake protocol saved in channel attribute. */ + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .persistentConnection(false) + .build(); + + private ProbingAction probingAction; + + private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) + throws Exception { + SslContext sslContext = SslContextBuilder.forServer(privateKey, certificate).build(); + return new SniHandler( + hostname -> { + sniHostReceived = hostname; + return sslContext; + }); + } + + private void setupProbingAction(Channel channel) { + probingAction = ExistingChannelAction.builder() + .delay(Duration.ZERO) + .host(SSL_HOST) + .channel(channel) + .outboundMessage(DEFAULT_MESSAGE) + .protocol(PROTOCOL) + .build(); + } + + @Test + public void testSuccess_swappedInitializerWithSslHandler() throws Exception { + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider); + EmbeddedChannel channel = new EmbeddedChannel(); + setupProbingAction(channel); + channel.attr(PROBING_ACTION_KEY).set(probingAction); + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(sslClientInitializer); + ChannelHandler firstHandler = pipeline.first(); + assertThat(firstHandler.getClass()).isEqualTo(SslHandler.class); + SslHandler sslHandler = (SslHandler) firstHandler; + assertThat(sslHandler.engine().getPeerHost()).isEqualTo(SSL_HOST); + assertThat(sslHandler.engine().getPeerPort()).isEqualTo(SSL_PORT); + assertThat(channel.isActive()).isTrue(); + } + + @Test + public void testSuccess_protocolAttributeNotSet() { + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider); + EmbeddedChannel channel = new EmbeddedChannel(); + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(sslClientInitializer); + // Channel initializer swallows error thrown, and closes the connection. + assertThat(channel.isActive()).isFalse(); + } + + @Test + public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Exception { + SelfSignedCertificate ssc = new SelfSignedCertificate(SSL_HOST); + LocalAddress localAddress = + new LocalAddress("DEFAULT_TRUST_MANAGER_REJECT_SELF_SIGNED_CERT_" + sslProvider); + nettyRule.setUpServer(localAddress, getServerHandler(ssc.key(), ssc.cert())); + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider); + + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + // The connection is now terminated, both the client side and the server side should get + // exceptions. + nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); + nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); + assertThat(nettyRule.getChannel().isActive()).isFalse(); + } + + @Test + public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws Exception { + LocalAddress localAddress = + new LocalAddress("CUSTOM_TRUST_MANAGER_ACCEPT_CERT_SIGNED_BY_TRUSTED_CA_" + sslProvider); + + // Generate a new key pair. + KeyPair keyPair = getKeyPair(); + + // Generate a self signed certificate, and use it to sign the key pair. + SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Certificate cert = signKeyPair(ssc, keyPair, SSL_HOST); + + // Set up the server to use the signed cert and private key to perform handshake; + PrivateKey privateKey = keyPair.getPrivate(); + nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); + + // Set up the client to trust the self signed cert used to sign the cert that server provides. + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + + setUpSslChannel(nettyRule.getChannel(), cert); + nettyRule.assertThatMessagesWork(); + + // Verify that the SNI extension is sent during handshake. + assertThat(sniHostReceived).isEqualTo(SSL_HOST); + } + + @Test + public void testFailure_customTrustManager_wrongHostnameInCertificate() throws Exception { + LocalAddress localAddress = + new LocalAddress("CUSTOM_TRUST_MANAGER_WRONG_HOSTNAME_" + sslProvider); + + // Generate a new key pair. + KeyPair keyPair = getKeyPair(); + + // Generate a self signed certificate, and use it to sign the key pair. + SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Certificate cert = signKeyPair(ssc, keyPair, "wrong.com"); + + // Set up the server to use the signed cert and private key to perform handshake; + PrivateKey privateKey = keyPair.getPrivate(); + nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); + + // Set up the client to trust the self signed cert used to sign the cert that server provides. + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + + // When the client rejects the server cert due to wrong hostname, both the client and server + // should throw exceptions. + nettyRule.assertThatClientRootCause().isInstanceOf(CertificateException.class); + nettyRule.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST); + nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); + assertThat(nettyRule.getChannel().isActive()).isFalse(); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java new file mode 100644 index 00000000000..68b2919141d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java @@ -0,0 +1,95 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.truth.Truth.assertThat; + +import io.netty.channel.Channel; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.util.SelfSignedCertificate; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import javax.net.ssl.SSLSession; +import javax.security.auth.x500.X500Principal; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.x509.X509V3CertificateGenerator; + +/** + * Utility class that provides methods used by {@link SslClientInitializerTest} + */ +public class SslInitializerTestUtils { + + static { + Security.addProvider(new BouncyCastleProvider()); + } + + public static KeyPair getKeyPair() throws Exception { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); + keyPairGenerator.initialize(2048, new SecureRandom()); + return keyPairGenerator.generateKeyPair(); + } + + /** + * Signs the given key pair with the given self signed certificate. + * + * @return signed public key (of the key pair) certificate + */ + public static X509Certificate signKeyPair( + SelfSignedCertificate ssc, KeyPair keyPair, String hostname) throws Exception { + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + X500Principal dnName = new X500Principal("CN=" + hostname); + certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); + certGen.setSubjectDN(dnName); + certGen.setIssuerDN(ssc.cert().getSubjectX500Principal()); + certGen.setNotBefore(Date.from(Instant.now().minus(Duration.ofDays(1)))); + certGen.setNotAfter(Date.from(Instant.now().plus(Duration.ofDays(1)))); + certGen.setPublicKey(keyPair.getPublic()); + certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); + return certGen.generate(ssc.key(), "BC"); + } + + /** + * Verifies tha the SSL channel is established as expected, and also sends a message to the server + * and verifies if it is echoed back correctly. + * + * @param certs The certificate that the server should provide. + * @return The SSL session in current channel, can be used for further validation. + */ + static SSLSession setUpSslChannel( + Channel channel, + X509Certificate... certs) + throws Exception { + SslHandler sslHandler = channel.pipeline().get(SslHandler.class); + // Wait till the handshake is complete. + sslHandler.handshakeFuture().get(); + + assertThat(channel.isActive()).isTrue(); + assertThat(sslHandler.handshakeFuture().isSuccess()).isTrue(); + assertThat(sslHandler.engine().getSession().isValid()).isTrue(); + assertThat(sslHandler.engine().getSession().getPeerCertificates()) + .asList() + .containsExactlyElementsIn(certs); + // Returns the SSL session for further assertion. + return sslHandler.engine().getSession(); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 19e608c97d2..518bb9ba686 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,27 +14,26 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; /** - * Concrete implementation of {@link ActionHandler} that does nothing different from parent class - * other than store and return the {@code inboundMessage} + * Concrete implementation of {@link ActionHandler} that does nothing different from + * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ - private InboundMessageType receivedMessage; + private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage; + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } - public InboundMessageType getResponse() { + @Override + public String toString() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 63bb2cf5b53..71d8d66b6c0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,32 +15,45 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; +import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ +/** + * Unit tests for {@link WebWhoisActionHandler}. + * + *

Attempts to test how well {@link WebWhoisActionHandler} works + * when responding to all possible types of responses

+ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; @@ -50,80 +63,85 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; + private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); + private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - + private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; + private ProbingAction probingAction; + private Provider actionHandlerProvider; + private void generateLocalAddress() { + address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + } /** Creates default protocol with empty list of handlers and specified other inputs */ private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() .name(name) .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); + .handlerProviders(ImmutableList.of(actionHandlerProvider)) + .persistentConnection(false) + .build(); } /** Initializes new WebWhoisActionHandler */ private void setupActionHandler() { actionHandler = new WebWhoisActionHandler(); + actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); + private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + setupProbingActionBasic( + protocol, + outboundMessage, + makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); } + private Bootstrap makeBootstrap(EventLoopGroup group) { + return new Bootstrap() + .group(group) + .channel(LocalChannel.class); + } /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() + private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + probingAction = NewChannelAction.builder() .protocol(protocol) .outboundMessage(outboundMessage) .delay(DEFAULT_DURATION) .bootstrap(bootstrap) + .host(TARGET_HOST) + .address(DEFAULT_ADDRESS) .build(); } - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); + private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(host) + .address(address) + .build(); } - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; + private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testSuccess_responseOk() { + public void testBasic_responseOk() throws Exception { //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); - + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); @@ -146,10 +164,13 @@ public void testSuccess_responseOk() { } @Test - public void testSuccess_responseBad() { + public void testBasic_responseFailure() { //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseBad", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); @@ -158,7 +179,8 @@ public void testSuccess_responseBad() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + FullHttpResponse response = HttpResponseMessage + .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -172,19 +194,57 @@ public void testSuccess_responseBad() { //ensures Protocol is the same assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } + @Test + public void testBasic_responseError() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseError", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + + //stores future + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, and event is success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + } @Test - public void testSuccess_redirectCloseChannel() { + public void testBasic_redirectCloseChannel() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); + HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", 0); + generateLocalAddress(); + setupChannel(initialProtocol, outboundMessage); //stores future ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + //checks that future has not been set to successful or a failure + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); @@ -195,27 +255,69 @@ public void testSuccess_redirectCloseChannel() { } @Test - public void testSuccess_redirectHost() { + public void testBasic_redirectHost() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); channel.writeInbound(originalResponse); + ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); + Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); + assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); + } + + @Test + public void testAdvanced_responseOk() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", TARGET_HOST, group); + //stores future + ChannelFuture future = probingAction.call(); + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + } + + @Test + public void testAdvanced_responseFailure() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", TARGET_HOST, group); + + //stores future + ChannelFuture future = probingAction.call(); + + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } } + From 7ba73acd20c4963afe9a011135e7beccd790a268 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 034/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 +++++++++----- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/ProbingSequence.java | 1 - .../monitoring/blackbox/ProbingStep.java | 7 +--- .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 - .../monitoring/blackbox/Tokens/Token.java | 4 +- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../monitoring/blackbox/WebWhoisModule.java | 2 +- .../exceptions/EppClientException.java | 29 ------------- .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++- .../handlers/WebWhoisMessageHandler.java | 22 +++++++++- .../blackbox/messages/HttpRequestMessage.java | 41 +++++++++++++------ .../messages/HttpResponseMessage.java | 26 ++++++++---- .../blackbox/messages/InboundMessageType.java | 1 - .../messages/OutboundMessageType.java | 1 - .../blackbox/TestServers/TestServer.java | 16 +++++++- .../blackbox/TestServers/WebWhoisServer.java | 18 +++++++- 20 files changed, 145 insertions(+), 86 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6387207fea4..2eb90a1d6c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -119,4 +119,3 @@ public String toString() { } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 5bad5abf6bf..80b04a3d0c9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.exceptions.EppClientException; import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; import io.netty.channel.local.LocalAddress; -import java.io.IOException; + import java.util.function.Consumer; import org.joda.time.Duration; @@ -164,7 +162,4 @@ public String toString() { message(), parent); } - } - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 855d9c5b41a..0fc3a3e09c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -66,4 +66,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dba905c0e49..7200a1877e2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -197,4 +197,4 @@ static SslClientInitializer provideSslClientInitializer(SslPro } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 4afc5d95ba7..0acf223eb9e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; @@ -8,6 +22,11 @@ import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; +/** + * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} + * in case of reuse for redirection + */ public class WebWhoisMessageHandler extends MessageHandler { private HttpRequestMessage request; @@ -15,6 +34,7 @@ public class WebWhoisMessageHandler extends MessageHandler { @Inject public WebWhoisMessageHandler() {} + /** Retains {@link HttpRequestMessage} and calls super write method*/ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { request = (HttpRequestMessage) msg; @@ -23,9 +43,9 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) } + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - FullHttpResponse originalResponse = (FullHttpResponse) msg; InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..b06938d80a1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +31,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,16 +38,19 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + + request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + + return finalRequest; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..283b14440ac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,7 +33,7 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); @@ -26,13 +43,8 @@ public static HttpResponseMessage fromResponse(FullHttpResponse response) { else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); return finalResponse; } - - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 0c1260becf2..578526933ba 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ public interface InboundMessageType {} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 0dd17e9d4a9..2d5df10f8c1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType {} - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 67e2cb7165d..a4474b6b8b5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static com.google.common.truth.Truth.assertThat; @@ -20,7 +34,7 @@ import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { private LocalAddress localAddress; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index ab9997b6c68..06b19ea3607 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -20,10 +34,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - * It will either redirect the client to the correct location if given the + *

It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location + * an unexpected host location

*/ public class WebWhoisServer extends TestServer { From f7ac3c4c68400f83b19af68fb851bff5070ba549 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 035/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 --- .../monitoring/blackbox/NewChannelAction.java | 144 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProberModule.java | 80 ++--- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingSequence.java | 130 ++++----- .../monitoring/blackbox/ProbingStep.java | 147 +++++----- .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/Protocol.java | 19 +- .../monitoring/blackbox/TokenModule.java | 35 --- .../monitoring/blackbox/Tokens/Token.java | 47 --- .../blackbox/Tokens/WebWhoisToken.java | 54 ---- .../monitoring/blackbox/WebWhoisModule.java | 169 ++++++----- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/ActionHandler.java | 105 +++++-- .../blackbox/handlers/MessageHandler.java | 24 -- .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../handlers/WebWhoisMessageHandler.java | 17 +- .../blackbox/messages/HttpRequestMessage.java | 46 ++- .../messages/HttpResponseMessage.java | 14 +- .../messages/OutboundMessageType.java | 11 +- .../monitoring/blackbox/tokens/Token.java | 43 +-- .../blackbox/tokens/WebWhoisToken.java | 62 ++-- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 32 files changed, 715 insertions(+), 973 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 73bd9127852..0daaf16ded4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,99 +14,59 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; import javax.inject.Singleton; +import org.joda.time.Duration; /** - * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} - * - *

Provides

+ * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores + * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. */ @Module public class ProberModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; + /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + private static final Duration DEFAULT_DURATION = new Duration(4000L); + + /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides - @HttpWhoisProtocol - ProbingSequence provideHttpWhoisSequence( - @HttpWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpsWhoisProtocol - ProbingSequence provideHttpsWhoisSequence( - @HttpsWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return httpWhoIsPort; - } - - @Provides - @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return httpsWhoIsPort; + @Singleton + Duration provideDuration() { + return DEFAULT_DURATION; } + /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - ImmutableMap providePortToProtocolMap( - Set protocolSet) { - return Maps.uniqueIndex(protocolSet, Protocol::port); + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - - + /** Root level {@link Component} that provides each {@link ProbingSequence}. */ @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, - TokenModule.class }) public interface ProberComponent { - @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); - - @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); - - ImmutableMap providePortToProtocolMap(); - - @WebWhoisProtocol Token provideWebWhoisToken(); + //Standard WebWhois sequence + @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2eb90a1d6c3..2dbf48256f9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,108 +14,100 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} - * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ - private EventLoopGroup eventGroup; + /**Each {@link ProbingSequence} requires a start token to begin running. */ + private Token startToken; - /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ - private Bootstrap bootstrap; - - public Bootstrap getBootstrap() { - return bootstrap; - } - - public void start(Token token) { - // calls the first step with input token; - firstStep.accept(token); + public void start() { + // calls the first step with startToken; + firstStep.accept(startToken); } /** - * {@link Builder} which takes in {@link ProbingStep}s - * - * @param Same specified {@code C} for overall {@link ProbingSequence} + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. */ - public static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstSequenceStep; - private EventLoopGroup eventLoopGroup; - private Class classType; - - Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public static class Builder { + + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstRepeatedStep; + private Bootstrap bootstrap; + private Token startToken; + + /** + * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. + * + *

Must be called before adding {@link ProbingStep.Builder}s.

+ */ + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } + + /** Adds start token that activate {@link ProbingSequence}. */ + public Builder addToken(Token token) { + startToken = token; return this; } - Builder addStep(ProbingStep step) { - if (currentStep == null) { + /** + * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * built, and pointed to by the previous {@link ProbingStep} added. + */ + public Builder addStep(ProbingStep.Builder stepBuilder) { + assert (bootstrap != null); + ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + + if (currentStep == null) firstStep = step; - } else { + else currentStep.nextStep(step); - } + currentStep = step; return this; } - /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ - Builder makeFirstRepeated() { - firstSequenceStep = currentStep; - return this; - } - /** Set the class to be the same as {@code C} */ - public Builder setClass(Class classType) { - this.classType = classType; + /** We take special note of the first repeated step. */ + public Builder markFirstRepeated() { + firstRepeatedStep = currentStep; return this; } - public ProbingSequence build() { - currentStep.nextStep(firstSequenceStep); + /** + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and + * calls private constructor to create {@link ProbingSequence}. + */ + public ProbingSequence build() { + if (firstRepeatedStep == null) + firstRepeatedStep = firstStep; + + currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); - return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + return new ProbingSequence(this.firstStep, this.startToken); } - } - /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ - private void setParents() { - ProbingStep currentStep = firstStep.parent(this).nextStep(); - - while (currentStep != firstStep) { - currentStep = currentStep.parent(this).nextStep(); - } - } - private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, - Class classType) { + private ProbingSequence(ProbingStep firstStep, Token startToken) { this.firstStep = firstStep; - this.eventGroup = eventLoopGroup; - this.bootstrap = new Bootstrap() - .group(eventGroup) - .channel(classType); - setParents(); - } - - @Override - public String toString() { - return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); - + this.startToken = startToken; } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 80b04a3d0c9..d54acef325a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,152 +14,145 @@ package google.registry.monitoring.blackbox; +import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.local.LocalAddress; - import java.util.function.Consumer; import org.joda.time.Duration; /** - * Represents generator of actions performed at each step in {@link ProbingSequence} - * - * @param See {@code C} in {@link ProbingSequence} + * {@link AutoValue} class that represents generator of actions performed at each step + * in {@link ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies - * these components on each loop iteration with the consumed {@link Token} and from that, - * generates new {@link ProbingAction} to perform<./p> + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. + * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, + * generates a new {@link ProbingAction} to call.

* - *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -public abstract class ProbingStep implements Consumer { +@AutoValue +public abstract class ProbingStep implements Consumer { - public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); - protected static final Duration DEFAULT_DURATION = new Duration(2000L); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - protected LocalAddress address = DEFAULT_ADDRESS; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ private boolean isLastStep = false; - private ProbingStep nextStep; - private ProbingSequence parent; + private ProbingStep nextStep; - protected Duration duration; + abstract Duration duration(); + abstract Protocol protocol(); + abstract OutboundMessageType messageTemplate(); + abstract Bootstrap bootstrap(); - protected final Protocol protocol; - protected final OutboundMessageType message; - protected ProbingStep(Protocol protocol, OutboundMessageType message) { - this.protocol = protocol; - this.message = message; - } + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder setDuration(Duration value); - private OutboundMessageType message() { - return message; - } + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); - Protocol protocol() { - return protocol; + public abstract ProbingStep build(); } + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - ProbingStep parent(ProbingSequence parent) { - this.parent = parent; - return this; - } - - /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ private ProbingAction generateAction(Token token) throws InternalException { - ProbingAction generatedAction; - - OutboundMessageType message = token.modifyMessage(message()); - - //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction - if (protocol().persistentConnection() && token.channel() != null) { - generatedAction = ExistingChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .channel(token.channel()) - .build(); - } else { - generatedAction = NewChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .bootstrap(parent.getBootstrap()) - .address(address) - .build(); - - } - return generatedAction; + OutboundMessageType message = token.modifyMessage(messageTemplate()); + ProbingAction.Builder probingActionBuilder = ProbingAction.builder() + .setDelay(duration()) + .setProtocol(protocol()) + .setOutboundMessage(message) + .setHost(token.getHost()) + .setBootstrap(bootstrap()); + + if (token.channel() != null) + probingActionBuilder.setChannel(token.channel()); + + return probingActionBuilder.build(); } - /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } @Override public void accept(Token token) { - ProbingAction nextAction; + ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - nextAction = generateAction(token); + currentAction = generateAction(token); } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - //If the next step maintains the connection, pass on the channel from this - if (protocol().persistentConnection()) { - token.channel(nextAction.channel()); - } + //call the created action - ChannelFuture future = nextAction.call(); + ChannelFuture future; + + try { + future = currentAction.call(); + + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Performed"); + nextStep.accept(generateNextToken(token)); + return; + } + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - nextStep.accept(generateNextToken(token)); + //If the next step maintains the connection, pass on the channel from this } else { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + token.setChannel(currentAction.channel()); + + nextStep.accept(generateNextToken(token)); + + }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n" + - "and parent sequence: %s", + "OutboundMessage: %s\n", protocol(), - message(), - parent); + messageTemplate().getClass().getName()); } + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 0fc3a3e09c3..ef52cb9c4bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -17,14 +17,18 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import io.netty.channel.ChannelHandler; +import io.netty.util.AttributeKey; import javax.inject.Provider; /** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. */ @AutoValue public abstract class Protocol { + /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + abstract String name(); public abstract int port(); @@ -35,22 +39,21 @@ public abstract class Protocol { /** Boolean that notes if connection associated with Protocol is persistent.*/ abstract boolean persistentConnection(); - public abstract Builder toBuilder(); - public static Builder builder() { return new AutoValue_Protocol.Builder(); } + /** Builder for {@link Protocol}. */ @AutoValue.Builder - public static abstract class Builder { + public abstract static class Builder { - public abstract Builder name(String value); + public abstract Builder setName(String value); - public abstract Builder port(int num); + public abstract Builder setPort(int num); - public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder setHandlerProviders(ImmutableList> providers); - public abstract Builder persistentConnection(boolean value); + public abstract Builder setPersistentConnection(boolean value); public abstract Protocol build(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 7200a1877e2..dcc9635beaa 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,62 +17,86 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; -import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandler; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - final static String DOMAIN_SUFFIX = "whois.nic."; + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + private static final String DOMAIN_PREFIX = "whois.nic."; + + /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + private static final int maximumMessageLengthBytes = 512 * 1024; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - - - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - - + /** {@link Provides} standard WebWhois sequence. */ @Provides - @HttpWhoisProtocol - static ProbingStep provideHttpWhoisProbingSequence( - @HttpWhoisProtocol Protocol httpWhoisProtocol) { - return new ProbingStepWeb<>(httpWhoisProtocol); + @WebWhoisProtocol + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, + WebWhoisToken webWhoisToken, + @WebWhoisProtocol Bootstrap bootstrap) { + + return new ProbingSequence.Builder() + .addToken(webWhoisToken) + .setBootstrap(bootstrap) + .addStep(probingStepBuilder) + .build(); } + + /** {@link Provides} only step used in WebWhois sequence. */ @Provides - @HttpsWhoisProtocol - static ProbingStep provideHttpsWhoisProbingStep( - @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { - return new ProbingStepWeb<>(httpsWhoisProtocol); + @WebWhoisProtocol + static ProbingStep.Builder provideWebWhoisStepBuilder( + @HttpWhoisProtocol Protocol httpWhoisProtocol, + HttpRequestMessage messageTemplate, + Duration duration) { + + return ProbingStep.builder() + .setProtocol(httpWhoisProtocol) + .setMessageTemplate(messageTemplate) + .setDuration(duration); } - + /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides @HttpWhoisProtocol @@ -80,28 +104,14 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpProtocolForSet( - @HttpWhoisProtocol int httpWhoisPort, - @HttpWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTP_PROTOCOL_NAME) + .setPort(httpWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } - + /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ @Singleton @Provides @HttpsWhoisProtocol @@ -109,40 +119,28 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpsProtocolForSet( - @HttpsWhoisProtocol int httpsWhoisPort, - @HttpsWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTPS_PROTOCOL_NAME) + .setPort(httpsWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } + /** {@link Provides} the prefix where we probe: "prefix.tld". */ @Provides - @WebWhoisProtocol - String provideHttpWhoisHost() { - return "app"; + @Named("Web-WHOIS-Prefix") + String provideWhoisPrefix() { + return DOMAIN_PREFIX; } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -151,13 +149,14 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -167,33 +166,57 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } + @Provides + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); + } + + @Provides + static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { + return new HttpObjectAggregator(maxContentLength); + } + + /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + @Provides + @HttpsWhoisProtocol + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); + } + /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + @Singleton @Provides @WebWhoisProtocol - static MessageHandler provideMessageHandler() { - return new WebWhoisMessageHandler(); + static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + return new Bootstrap() + .group(eventLoopGroup) + .channel(NioSocketChannel.class); } @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); + @WebWhoisProtocol + int provideMaximumMessageLengthBytes() { + return maximumMessageLengthBytes; } + /** {@link Provides} the list of top level domains to be probed */ + @Singleton @Provides - static HttpObjectAggregator provideHttpObjectAggregator() { - return new HttpObjectAggregator(1048576); + @WebWhoisProtocol + ImmutableList provideTopLevelDomains() { + return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); } @Provides - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index 776a231d6dd..be3d725c833 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,10 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when the action - * performed failed due to an issue in the connection with the server. + * Base exception class for all instances when the status of the action performed is ERROR. */ -public class ConnectionException extends UndeterminedStateException { +public class ConnectionException extends Exception { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index c3622e1b810..2e155b40afd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,10 +14,11 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.ChannelFuture; @@ -26,17 +27,18 @@ import io.netty.channel.SimpleChannelInboundHandler; /** - * Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, - * as it should only be passed in messages that implement the {@link InboundMessageType} interface. + *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link - * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. - * Second, it stores the {@link OutboundMessageType} passed down the pipeline, so that subclasses - * can use that information for their own processes. Lastly, with any exception thrown, the - * connection is closed, and the ProbingAction governing this channel is informed of the error. - * Subclasses specify further work to be done for specific kinds of channel pipelines. + *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed + * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} + * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * + *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -48,33 +50,41 @@ public enum ResponseType {SUCCESS, FAILURE, ERROR} /** Status of response for current {@link ActionHandler} instance */ private static ResponseType status; + /** {@link ChannelPromise} that informs {@link google.registry.monitoring.blackbox.ProbingAction} if response has been received. */ protected ChannelPromise finished; - /** - * Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized - * {@link ChannelPromise} - */ + /** Returns initialized {@link ChannelPromise} to {@link google.registry.monitoring.blackbox.ProbingAction}.*/ public ChannelFuture getFuture() { return finished; } - /** Initializes new {@link ChannelPromise} */ + /** Initializes the same {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { // Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } + /** Initializes the same {@link ChannelPromise} in case current channel is reused (usually for EPP).*/ + public void resetFuture() { + finished = finished.channel().newPromise(); + } + + /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { - //simply marks finished as success + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { + status = ResponseType.SUCCESS; - finished.setSuccess(); + + if (!finished.isSuccess()) { + finished.setSuccess(); + } } /** - * Logs the channel and pipeline that caused error, closes channel, then informs {@link - * ProbingAction} listeners of error + * Logs the channel and pipeline that caused error, closes channel, then informs + * {@link google.registry.monitoring.blackbox.ProbingAction} listeners of error. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { @@ -83,27 +93,62 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", ctx.channel().toString(), ctx.channel().pipeline().toString())); - - if (ResponseException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + if (cause instanceof ResponseException) { + //On ResponseException, we know the response is a failure. As a result, + //we set the status to FAILURE, then inform the MetricsHandler of this status = ResponseType.FAILURE; + + //Since it wasn't a success, we still want to log to see what caused the FAILURE logger.atInfo().log(cause.getMessage()); + + //As always, inform the ProbingStep that we successfully completed this action finished.setSuccess(); - } else if (ServerSideException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + + } else if (cause instanceof ConnectionException) { + //On ConnectionException, we know the response type is an error. As a result, + //we set the status to ERROR, then inform the MetricsHandler of this status = ResponseType.ERROR; + + //Since it wasn't a success, we still log what caused the ERROR logger.atInfo().log(cause.getMessage()); finished.setSuccess(); - } else if (InternalException.class.isInstance(cause)){ + + //As this was an ERROR in the connection, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + } else if (cause instanceof InternalException){ + //For an internal error, metrics should not be collected, so we log what caused this, and + //inform the ProbingStep the Prober had an internal error on this action logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); + + + //As this was an internal error, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } else { - finished.setFailure(cause); + //In the case of any other kind of error, we assume it is some type of connection ERROR, + //so we treat it as such: + + status = ResponseType.ERROR; + + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - //due to failure, close channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + + } + + /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ + @VisibleForTesting + ResponseType getStatus() { + return status; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index ac844ac99df..919006592ea 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -89,8 +90,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); - Protocol protocol = action.protocol(); + Protocol protocol = channel.attr(PROTOCOL_KEY).get(); + String host = channel.attr(REMOTE_ADDRESS_KEY).get(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -103,7 +104,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), action.host(), protocol.port()); + .newHandler(channel.alloc(), host, protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 0acf223eb9e..58c395ad86e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -17,37 +17,36 @@ import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; /** - * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection + * in case of reuse for redirection. */ -public class WebWhoisMessageHandler extends MessageHandler { - - private HttpRequestMessage request; +public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method*/ + /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - request = (HttpRequestMessage) msg; + HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; - InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); + HttpResponseMessage response = new HttpResponseMessage(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b06938d80a1..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,19 +19,30 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); @@ -39,18 +50,29 @@ public HttpRequestMessage setUri(String path) { } /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; - ByteBuf buf = request.content(); + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; - request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + } else { + throw new IllegalArgumentException(); + } + } - return finalRequest; + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 283b14440ac..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -34,17 +34,9 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 2d5df10f8c1..be6c872cc3e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,16 @@ package google.registry.monitoring.blackbox.messages; +import google.registry.monitoring.blackbox.exceptions.InternalException; + /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType {} +public interface OutboundMessageType { + + /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + public OutboundMessageType modifyMessage(String... args) throws InternalException; + + /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + public String name(); +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index b10c45dae8a..dd1882b5686 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,58 +14,41 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.ProbingSequence; -import google.registry.monitoring.blackbox.ProbingStep; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} in a single loop of a - * {@link ProbingSequence}. + * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} + * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes on channel that remains unchanged within a - * loop of the sequence.

+ * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop * in the sequence.

*/ public abstract class Token { - /** - * {@link Channel} that always starts out as null. Once a persistent connection is made (such as - * EPP), that channel is stored in the token and passed on to later steps in the sequence until a - * new loop begins. - */ + /** {@link Channel} that always starts out as null. */ protected Channel channel; - /** - * Obtains next {@link Token} for next loop in sequence. - */ + /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); - /** - * String corresponding to host that is relevant for loop in sequence. - */ - public abstract String host(); + /** String corresponding to host that is relevant for loop in sequence. */ + public abstract String getHost(); - /** - * Modifies the {@link OutboundMessageType} in the manner necessary for each loop - */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) - throws UndeterminedStateException; + /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; - /** - * Set method for {@code channel} - */ + /** Set method for {@code channel} */ public void setChannel(Channel channel) { this.channel = channel; } - /** - * Get method for {@code channel}. - */ + /** Get method for {@code channel}. */ public Channel channel() { return this.channel; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 3ff852f3556..2847e5ce0eb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,67 +16,59 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; +import java.util.List; import javax.inject.Inject; +import javax.inject.Named; /** * {@link Token} subtype designed for WebWhois sequence. * *

Between loops of a WebWhois sequence the only thing changing is the tld we - * are probing. As a result, we maintain the list of {@code topLevelDomains} and on each call to - * next, have our index looking at the next {@code topLevelDomain}.

+ * are probing. As a result, we maintain the list of {@code topLevelDomains} and + * on each call to next, have our index looking at the next {@code topLevelDomain}.

*/ public class WebWhoisToken extends Token { - /** - * For each top level domain (tld), we probe "prefix.tld". - */ - private static final String PREFIX = "whois.nic."; + /** For each top level domain (tld), we probe "prefix.tld". */ + private final String prefix; - /** - * {@link ImmutableList} of all top level domains to be probed. - */ - private final Iterator topLevelDomainsIterator; + /** {@link ImmutableList} of all top level domains to be probed. */ + private final ImmutableList topLevelDomains; - /** - * Current index of {@code topLevelDomains} that represents tld we are probing. - */ - private String currentDomain; + /** Current index of {@code topLevelDomains} that represents tld we are probing. */ + private int domainsIndex; @Inject - public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken( + @Named("Web-WHOIS-Prefix") String prefix, + @WebWhoisProtocol ImmutableList topLevelDomains) { - topLevelDomainsIterator = topLevelDomains.iterator(); - currentDomain = topLevelDomainsIterator.next(); + domainsIndex = 0; + this.prefix = prefix; + this.topLevelDomains = topLevelDomains; } - /** - * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. - */ + /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + domainsIndex += 1; + domainsIndex %= topLevelDomains.size(); return this; } - /** - * Modifies message to reflect the new host coming from the new top level domain. - */ + /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) - throws UndeterminedStateException { - return original.modifyMessage(host()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { + return original.modifyMessage(getHost()); } - /** - * Returns host as the concatenation of fixed {@code prefix} and current value of {@code - * topLevelDomains}. - */ + /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String host() { - return PREFIX + currentDomain; + public String getHost() { + return prefix + topLevelDomains.get(domainsIndex); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Mon, 29 Jul 2019 12:04:58 -0400 Subject: [PATCH 036/337] Minor Style Fixes --- .../monitoring/blackbox/ProbingAction.java | 85 ++++++++++--------- .../monitoring/blackbox/ProbingStep.java | 8 +- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..3f6a962b12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -89,11 +90,47 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** The {@link SocketAddress} instance that specifies remote address of connection */ + @Nullable public abstract SocketAddress address(); /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ public abstract Optional bootstrap(); + + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> actionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** * The method that performs the work of the actual action. * @@ -130,41 +167,13 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } @@ -224,7 +233,7 @@ public abstract static class Builder { abstract Channel channel(); - abstract Optional address(); + abstract SocketAddress address(); abstract Optional bootstrap(); @@ -233,7 +242,7 @@ public abstract static class Builder { abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) + if (address() == null) //If no address has been supplied, we set it based on the host and port setAddress(new InetSocketAddress(host(), protocol().port())); @@ -259,7 +268,7 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap().get().connect(address()); setChannel(connectionFuture.channel()); setConnectionFuture(connectionFuture); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index d54acef325a..47c89c72c11 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -21,7 +21,9 @@ import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import java.net.SocketAddress; import java.util.function.Consumer; +import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -48,6 +50,7 @@ public abstract class ProbingStep implements Consumer { abstract Protocol protocol(); abstract OutboundMessageType messageTemplate(); abstract Bootstrap bootstrap(); + @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -60,6 +63,8 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); + public abstract Builder setAddress(SocketAddress address); + public abstract ProbingStep build(); } @@ -87,7 +92,8 @@ private ProbingAction generateAction(Token token) throws InternalException { .setProtocol(protocol()) .setOutboundMessage(message) .setHost(token.getHost()) - .setBootstrap(bootstrap()); + .setBootstrap(bootstrap()) + .setAddress(address()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); From ee1a6be42e5aa583775663942311cfc2753a0657 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:05:59 -0400 Subject: [PATCH 037/337] Updated build.gradle file --- prober/build.gradle | 3 - .../blackbox/ProbingSequenceStepTest.java | 219 ----------------- .../blackbox/ProbingSequenceTest.java | 87 ------- .../monitoring/blackbox/ProbingStepTest.java | 232 +++++++++--------- 4 files changed, 120 insertions(+), 421 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java diff --git a/prober/build.gradle b/prober/build.gradle index 993da44655d..181188c5cee 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,7 +16,6 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - dependencies { def deps = rootProject.dependencyMap @@ -45,7 +44,6 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -55,4 +53,3 @@ dependencies { testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java deleted file mode 100644 index 7a713017072..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.TestUtils.TestStep; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.handlers.ConversionHandler; -import google.registry.monitoring.blackbox.handlers.NettyRule; -import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; -import org.junit.Rule; -import org.junit.Test; - -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { - - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ - private ProbingSequence testSequence; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); - dummyStep = new DummyStep(testProtocol, eventLoopGroup); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(false) - .build(); - } - - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(true) - .build(); - } - - /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ - private void setupSequence() { - testSequence = new ProbingSequence.Builder() - .eventLoopGroup(eventLoopGroup) - .setClass(LocalChannel.class) - .addStep(firstStep) - .makeFirstRepeated() - .addStep(dummyStep) - .build(); - } - - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.nextStep()).isNull(); - - //we expect that this exception be thrown - assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); - - } - - @Test - public void testWithSequence_NewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupSequence(); - setupNewChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupSequence(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 02599bcb51a..2b0559514a2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,92 +1,5 @@ -// Copyright 2019 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.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import google.registry.monitoring.blackbox.tokens.Token; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) public class ProbingSequenceTest { - private ProbingStep firstStep; - private ProbingStep secondStep; - private ProbingStep thirdStep; - - private Token testToken; - - private ProbingStep setupMockStep() { - ProbingStep mock = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(mock).nextStep(); - return mock; - } - - @Before - public void setup() { - firstStep = setupMockStep(); - secondStep = setupMockStep(); - thirdStep = setupMockStep(); - - testToken = Mockito.mock(Token.class); - } - - @Test - public void testSequenceBasicConstruction_Success() { - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(firstStep) - .addStep(secondStep) - .addStep(thirdStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(thirdStep); - assertThat(thirdStep.nextStep()).isEqualTo(firstStep); - - sequence.start(); - - verify(firstStep, times(1)).accept(testToken); - } - - @Test - public void testSequenceAdvancedConstruction_Success() { - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(thirdStep) - .addStep(secondStep) - .markFirstRepeated() - .addStep(firstStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(firstStep); - assertThat(thirdStep.nextStep()).isEqualTo(secondStep); - - sequence.start(); - - verify(thirdStep, times(1)).accept(testToken); - } - } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index db7ec271956..090753014e4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,192 +11,200 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.TestUtils.dummyStep; +import static google.registry.monitoring.blackbox.TestUtils.testStep; +import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import org.joda.time.Duration; -import org.junit.Ignore; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; import org.junit.Rule; import org.junit.Test; -import org.mockito.Mockito; - -/** - * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific - * implementations - */ -public class ProbingStepTest { - - /** - * Basic Constants necessary for tests - */ - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final int PROTOCOL_PORT = 0; - private static final String TEST_MESSAGE = "TEST_MESSAGE"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - private static final LocalAddress ADDRESS = new LocalAddress(ADDRESS_NAME); + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - /** - * Used for testing how well probing step can create connection to blackbox server - */ + /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** - * The two main handlers we need in any test pipeline used that connects to {@link NettyRule's - * server} - **/ + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** - * Creates mock {@link Token} object that returns the host and returns unchanged message when - * modifying it. - */ - private Token testToken(String host) throws UndeterminedStateException { - Token token = Mockito.mock(Token.class); - doReturn(host).when(token).host(); - doAnswer(answer -> answer.getArgument(0)).when(token) - .modifyMessage(any(OutboundMessageType.class)); - return token; + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); } - @Test - public void testNewChannel() throws Exception { - // Sets up Protocol for when we create a new channel. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); + dummyStep = dummyStep(eventLoopGroup); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); + } - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) .build(); + } + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + //there should be no next step + assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); - firstStep.nextStep(dummyStep); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = testToken(ADDRESS_NAME); + } - //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(ADDRESS); + @Test + public void testNewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //checks that we have appropriately sent the write message to server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - verify(dummyStep, times(1)).accept(any(Token.class)); + assertThat(future.get()).isEqualTo(testToken); + } - //TODO - Currently, this test fails to receive outbound messages from the embedded channel, which - // we will fix in a later release. - @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - // Sets up Protocol for when a channel already exists. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) - .build(); - - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) - .build(); - - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - - firstStep.nextStep(dummyStep); - - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - - //Assures that the channel has a succeeded connectionFuture. - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = testToken(""); - doReturn(channel).when(testToken).channel(); + //setup + setupExistingProtocol(); + setupSteps(); + setupChannel(); + setupExistingChannelToken(); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message through the EmbeddedChannel - // pipeline + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); - Object msg = channel.readOutbound(); - - while (msg == null) { - msg = channel.readOutbound(); - } //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf) channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked - // as a success - verify(dummyStep, times(1)).accept(any(Token.class)); + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + } } From d9be259deeaeae65bbc03ef5aff021a6c16100de Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 038/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From 520645b0421b317dde2786887f37f3269167639b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:54:13 -0400 Subject: [PATCH 039/337] Updated WebWhois tests. --- .../blackbox/ProbingActionTest.java | 56 +++--- .../blackbox/ProbingSequenceTest.java | 183 ++++++++++++++++++ .../monitoring/blackbox/ProbingStepTest.java | 3 +- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 93 +++++++-- .../monitoring/blackbox/TokenTest.java | 13 +- .../blackbox/handlers/ConversionHandler.java | 2 +- .../blackbox/handlers/NettyRule.java | 12 +- .../handlers/SslClientInitializerTest.java | 46 ++--- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 158 ++++++++------- 11 files changed, 421 insertions(+), 157 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index cbcf2fc82b0..162044c2036 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -83,31 +84,31 @@ public class ProbingActionTest { /** Sets up a {@link Protocol} corresponding to when a new connection is created */ private void setupNewChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(false) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) .build(); } /** Sets up a {@link Protocol} corresponding to when a new connection exists */ private void setupExistingChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(true) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(true) .build(); } - /** Sets up a {@link NewChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ private void setupNewChannelAction() { - newChannelAction = NewChannelAction.builder() - .bootstrap(bootstrap) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") - .address(address) + newChannelAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") + .setAddress(address) .build(); } @@ -115,25 +116,25 @@ private void setupChannel() { channel = new EmbeddedChannel(); } - /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ExistingChannelAction.builder() - .channel(channel) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") + existingChannelAction = ProbingAction.builder() + .setChannel(channel) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") .build(); } @Test - public void testBehavior_existingChannel() { + public void testBehavior_existingChannel() throws InternalException { //setup setupChannel(); setupExistingChannelProtocol(); - setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); + setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -147,6 +148,7 @@ public void testBehavior_existingChannel() { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -156,9 +158,9 @@ public void testBehavior_existingChannel() { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - setupNewChannelAction(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + setupNewChannelAction(); ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2b0559514a2..681a5346d55 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,5 +1,188 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; + +import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; +import java.net.SocketAddress; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) public class ProbingSequenceTest { + private final static String TEST_HOST = "TEST_HOST"; + + + private Bootstrap dummyBootstrap = new Bootstrap(); + private Token testToken = new ProbingSequenceTestToken(); + + /** + * Custom {@link ProbingStep} subclass that acts as a mock + * step, so we can test how well {@link ProbingSequence} builds + * a linked list of {@link ProbingStep}s from their {@link Builder}s. + */ + private static class TestStep extends ProbingStep { + private Bootstrap bootstrap; + private String marker; + + /** We implement all abstract methods to simply return null, as we have no use for them here. */ + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + SocketAddress address() { + return null; + } + + /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + /** + * Builder for {@link TestStep}, that extends {@link ProbingStep.Builder} so that these can be + * input into the {@link ProbingSequence.Builder}. + */ + public static class Builder extends ProbingStep.Builder { + /** We test to see if we accurately add the right bootstrap to all {@link ProbingStep}s/ */ + private Bootstrap bootstrap; + + /** We also mark each step in order to ensure that when running, they are arranged in the right order. */ + private String marker; + + @Override + public ProbingStep.Builder setDuration(Duration value) { + return this; + } + + @Override + public ProbingStep.Builder setProtocol(Protocol value) { + return this; + } + + @Override + public ProbingStep.Builder setMessageTemplate(OutboundMessageType value) { + return null; + } + + @Override + public ProbingStep.Builder setAddress(SocketAddress address) { + return null; + } + + @Override + public ProbingStep.Builder setBootstrap(Bootstrap value) { + bootstrap = value; + return this; + } + + public ProbingStep.Builder addMarker(String value) { + marker = value; + return this; + } + + @Override + public ProbingStep build() { + return new TestStep(bootstrap, marker); + } + } + private TestStep(Bootstrap bootstrap, String marker) { + this.bootstrap = bootstrap; + this.marker = marker; + } + + /** + * On a call to accept, we modify the token to reflect what the current step is, so we can get + * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated + * in order. + */ + @Override + public void accept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + if (!isLastStep) { + nextStep().accept(token); + } else { + ((TestStep)nextStep()).specialAccept(token); + } + } + + /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ + public void specialAccept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + return; + } + } + + @Test + public void testSequenceBasicConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("firstsecondthirdfirst"); + } + + @Test + public void testSequenceAdvancedConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(thirdStepBuilder) + .addStep(secondStepBuilder) + .markFirstRepeated() + .addStep(firstStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("thirdsecondfirstsecond"); + } + @Test + public void testSequenceConstruction_Failure() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + assertThrows(AssertionError.class, () -> { + ProbingSequence sequence = new ProbingSequence.Builder() + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .setBootstrap(dummyBootstrap) + .build(); + }); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 090753014e4..ee38e7cdf74 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -21,7 +21,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; @@ -47,7 +46,7 @@ import org.junit.Test; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { +public class ProbingStepTest { /** Basic Constants necessary for tests */ private final String ADDRESS_NAME = "TEST_ADDRESS"; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 06b19ea3607..337d755e971 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -93,11 +93,11 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 8d1722c9625..161304c1f04 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,9 +17,11 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -37,6 +39,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; +import java.net.Socket; +import java.net.SocketAddress; +import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -141,26 +146,67 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } + + @Override + public OutboundMessageType modifyMessage(String... args) throws InternalException { + message = args[0]; + return this; + } + + @Override + public String name() { + return "Test Message of: " + this.toString(); + } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static class TestStep extends ProbingStep { + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .setAddress(address) + .build(); - public TestStep(Protocol protocol, String testMessage, LocalAddress address) { - super(protocol, new DuplexMessageTest(testMessage)); - this.address = address; - this.duration = Duration.ZERO; - } + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { - super(protocol, new DuplexMessageTest()); - future = new DefaultPromise(eventLoopGroup.next()) {}; - duration = Duration.ZERO; + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; + } + + @Nullable + @Override + SocketAddress address() { + return null; } @Override @@ -170,11 +216,16 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } + + @Override + public String toString() { + return "Dummy Step"; + } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - private String host; + protected String host; protected TestToken(String host) { this.host = host; @@ -221,6 +272,22 @@ public Channel channel() { } } + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..67963805733 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,10 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; @@ -34,20 +35,20 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..a8506a996a9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -37,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b6b5e8fbe0c..b38c1911940 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; @@ -89,7 +90,8 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - ProbingAction probingAction, + Protocol protocol, + String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -109,7 +111,9 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROBING_ACTION_KEY, probingAction); + .attr(PROTOCOL_KEY, protocol) + .attr(REMOTE_ADDRESS_KEY, host); + channel = b.connect(localAddress).syncUninterruptibly().channel(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 469c62a8f75..83c8e132f07 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,17 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ExistingChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; @@ -45,7 +46,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; -import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,8 +67,6 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); - /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -93,15 +91,12 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .persistentConnection(false) - .build(); - - private ProbingAction probingAction; + private final static Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -113,23 +108,13 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } - private void setupProbingAction(Channel channel) { - probingAction = ExistingChannelAction.builder() - .delay(Duration.ZERO) - .host(SSL_HOST) - .channel(channel) - .outboundMessage(DEFAULT_MESSAGE) - .protocol(PROTOCOL) - .build(); - } - @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - setupProbingAction(channel); - channel.attr(PROBING_ACTION_KEY).set(probingAction); + channel.attr(PROTOCOL_KEY).set(PROTOCOL); + channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -160,8 +145,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -189,8 +173,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -219,8 +202,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 518bb9ba686..e170fad8b8c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox.handlers; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 71d8d66b6c0..00318ccd912 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,17 +15,17 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; @@ -37,9 +37,7 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; @@ -66,6 +64,14 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); + private static final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of()) + .setName("test_protocol") + .setPersistentConnection(false) + .setPort(HTTPS_PORT) + .build(); + private LocalAddress address; private EmbeddedChannel channel; @@ -76,30 +82,38 @@ public class WebWhoisActionHandlerTest { private void generateLocalAddress() { address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); } + /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { + private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of(actionHandlerProvider)) - .persistentConnection(false) + .setName(name) + .setPort(port) + .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) + .setPersistentConnection(persistentConnection) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); + private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { + actionHandler = new WebWhoisActionHandler( + bootstrap, + STANDARD_PROTOCOL, + STANDARD_PROTOCOL, + messageTemplate, + 80, + 443 + ); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); setupProbingActionBasic( protocol, outboundMessage, makeBootstrap(new NioEventLoopGroup(1))); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -109,24 +123,25 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { } /**Sets up probingAction for when testing redirection */ private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(TARGET_HOST) - .address(DEFAULT_ADDRESS) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(TARGET_HOST) + .setAddress(DEFAULT_ADDRESS) + .setChannel(channel) .build(); } private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(host) - .address(address) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(host) + .setAddress(address) .build(); } @@ -137,10 +152,13 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, true); generateLocalAddress(); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); @@ -150,7 +168,7 @@ public void testBasic_responseOk() throws Exception { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -166,9 +184,10 @@ public void testBasic_responseOk() throws Exception { @Test public void testBasic_responseFailure() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseBad", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseBad", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -179,8 +198,7 @@ public void testBasic_responseFailure() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage - .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -197,9 +215,10 @@ public void testBasic_responseFailure() { @Test public void testBasic_responseError() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseError", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseError", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -211,7 +230,7 @@ public void testBasic_responseError() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -222,26 +241,30 @@ public void testBasic_responseError() { assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_redirectCloseChannel() { //setup - HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", 0); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", 0, true); generateLocalAddress(); - setupChannel(initialProtocol, outboundMessage); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -257,12 +280,15 @@ public void testBasic_redirectCloseChannel() { @Test public void testBasic_redirectHost() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); generateLocalAddress(); setupChannel(initialProtocol, msg); - HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); //store future @@ -272,27 +298,24 @@ public void testBasic_redirectHost() { channel.writeInbound(originalResponse); - ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - //gets changed protocol - Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); - assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); } @Test - public void testAdvanced_responseOk() { + public void testAdvanced_responseOk() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); //stores future ChannelFuture future = probingAction.call(); @@ -302,15 +325,16 @@ public void testAdvanced_responseOk() { } @Test - public void testAdvanced_responseFailure() { + public void testAdvanced_responseFailure() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); //stores future ChannelFuture future = probingAction.call(); From 8165651892252bd39fdb6e0f3565606040b3c447 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 040/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- prober/.gitignore | 2 +- .../registry/monitoring/blackbox/Prober.java | 9 +- .../monitoring/blackbox/ProberModule.java | 15 ++- .../monitoring/blackbox/ProbingAction.java | 96 +++++++-------- .../monitoring/blackbox/ProbingSequence.java | 24 +--- .../monitoring/blackbox/ProbingStep.java | 55 ++++++--- .../monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 49 ++++---- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 30 ----- .../exceptions/ResponseException.java | 29 ----- .../UndeterminedStateException.java | 5 +- .../blackbox/handlers/ActionHandler.java | 102 ++++------------ .../handlers/WebWhoisActionHandler.java | 51 ++++---- .../blackbox/messages/HttpRequestMessage.java | 4 +- .../messages/HttpResponseMessage.java | 6 +- .../messages/OutboundMessageType.java | 7 +- .../monitoring/blackbox/tokens/Token.java | 20 +-- .../blackbox/tokens/WebWhoisToken.java | 32 +++-- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../blackbox/ProbingActionTest.java | 9 +- .../blackbox/ProbingSequenceTest.java | 114 +++--------------- .../monitoring/blackbox/ProbingStepTest.java | 4 +- .../monitoring/blackbox/TestUtils.java | 21 +--- .../monitoring/blackbox/TokenTest.java | 8 +- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 103 +++++----------- 31 files changed, 283 insertions(+), 529 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/.gitignore b/prober/.gitignore index c86568e7672..77b1e2de2de 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..307afd34d81 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +29,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 0daaf16ded4..1db97d1b581 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,14 +14,18 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.Set; import javax.inject.Singleton; import org.joda.time.Duration; @@ -33,7 +37,7 @@ public class ProberModule { /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = new Duration(4000L); + private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @@ -42,6 +46,12 @@ EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + @Provides + @Singleton + Class provideChannelClass() { + return NioSocketChannel.class; + } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides @Singleton @@ -51,6 +61,7 @@ Duration provideDuration() { /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides + @Singleton static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; @@ -66,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); + Set provideAllSequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 3f6a962b12d..67494dd5f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,25 +14,29 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -65,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -80,31 +87,18 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - @Nullable - public abstract SocketAddress address(); - - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { // Write appropriate outboundMessage to pipeline ChannelFuture channelFuture = actionHandler.getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> actionHandler.resetFuture(), - //inform ProbingStep of the status of our action future -> { if (future.isSuccess()) @@ -141,7 +135,7 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -154,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -180,19 +174,24 @@ public ChannelFuture performAction() throws InternalException { /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -210,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -221,40 +226,30 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract SocketAddress address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (address() == null) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + System.out.println("test"); + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -268,14 +263,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -293,7 +285,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2dbf48256f9..91c4165c068 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -49,32 +49,18 @@ public static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; private ProbingStep firstRepeatedStep; - private Bootstrap bootstrap; - private Token startToken; - /** - * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. - * - *

Must be called before adding {@link ProbingStep.Builder}s.

- */ - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } + private Token startToken; - /** Adds start token that activate {@link ProbingSequence}. */ - public Builder addToken(Token token) { - startToken = token; - return this; + public Builder(Token startToken) { + this.startToken = startToken; } /** - * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, * built, and pointed to by the previous {@link ProbingStep} added. */ - public Builder addStep(ProbingStep.Builder stepBuilder) { - assert (bootstrap != null); - ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + public Builder addStep(ProbingStep step) { if (currentStep == null) firstStep = step; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 47c89c72c11..ca980100067 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import java.net.SocketAddress; import java.util.function.Consumer; -import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -39,18 +37,23 @@ @AutoValue public abstract class ProbingStep implements Consumer { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ - private boolean isLastStep = false; + protected boolean isLastStep = false; private ProbingStep nextStep; + /** Time delay duration between actions. */ abstract Duration duration(); + + /** {@link Protocol} type for this step. */ abstract Protocol protocol(); + + /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ abstract OutboundMessageType messageTemplate(); + + /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ abstract Bootstrap bootstrap(); - @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -63,8 +66,6 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); - public abstract Builder setAddress(SocketAddress address); - public abstract ProbingStep build(); } @@ -85,18 +86,18 @@ ProbingStep nextStep() { } /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws InternalException { + private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) .setProtocol(protocol()) .setOutboundMessage(message) - .setHost(token.getHost()) - .setBootstrap(bootstrap()) - .setAddress(address()); + .setHost(token.host()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); + else + probingActionBuilder.setBootstrap(bootstrap()); return probingActionBuilder.build(); } @@ -107,44 +108,58 @@ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } + /** + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. + * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

+ */ @Override public void accept(Token token) { ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - //call the created action ChannelFuture future; - try { + //call the generated action future = currentAction.call(); - - } catch(InternalException e) { + } catch(UndeterminedStateException e) { + //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); + + //Move on to next step in ProbingSequence nextStep.accept(generateNextToken(token)); return; } - //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - //If the next step maintains the connection, pass on the channel from this + } else { + //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index ef52cb9c4bf..624f08fd4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -29,7 +29,7 @@ public abstract class Protocol { /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - abstract String name(); + public abstract String name(); public abstract int port(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dcc9635beaa..c5e41fea38b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,6 +18,7 @@ import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,6 +27,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; @@ -44,11 +46,10 @@ @Module public class WebWhoisModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - private static final String DOMAIN_PREFIX = "whois.nic."; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; + private static final String HTTP_PROTOCOL_NAME = "http"; + private static final String HTTPS_PROTOCOL_NAME = "https"; /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; @@ -68,16 +69,14 @@ public class WebWhoisModule { /** {@link Provides} standard WebWhois sequence. */ @Provides - @WebWhoisProtocol + @Singleton + @IntoSet ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, - WebWhoisToken webWhoisToken, - @WebWhoisProtocol Bootstrap bootstrap) { + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { - return new ProbingSequence.Builder() - .addToken(webWhoisToken) - .setBootstrap(bootstrap) - .addStep(probingStepBuilder) + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) .build(); } @@ -85,15 +84,18 @@ ProbingSequence provideWebWhoisSequence( /** {@link Provides} only step used in WebWhois sequence. */ @Provides @WebWhoisProtocol - static ProbingStep.Builder provideWebWhoisStepBuilder( + static ProbingStep provideWebWhoisStep( @HttpWhoisProtocol Protocol httpWhoisProtocol, + @WebWhoisProtocol Bootstrap bootstrap, HttpRequestMessage messageTemplate, Duration duration) { return ProbingStep.builder() .setProtocol(httpWhoisProtocol) + .setBootstrap(bootstrap) .setMessageTemplate(messageTemplate) - .setDuration(duration); + .setDuration(duration) + .build(); } /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @@ -126,13 +128,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** {@link Provides} the prefix where we probe: "prefix.tld". */ - @Provides - @Named("Web-WHOIS-Prefix") - String provideWhoisPrefix() { - return DOMAIN_PREFIX; - } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @@ -187,10 +182,12 @@ static SslClientInitializer provideSslClientInitializer(SslPro @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + static Bootstrap provideBootstrap( + EventLoopGroup eventLoopGroup, + Class channelClass){ return new Bootstrap() .group(eventLoopGroup) - .channel(NioSocketChannel.class); + .channel(channelClass); } @Provides @@ -210,13 +207,13 @@ ImmutableList provideTopLevelDomains() { @Provides @HttpWhoisProtocol int provideHttpWhoisPort() { - return httpWhoIsPort; + return HTTP_WHOIS_PORT; } @Provides @HttpsWhoisProtocol int provideHttpsWhoisPort() { - return httpsWhoIsPort; + return HTTPS_WHOIS_PORT; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index be3d725c833..adb833ec629 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,9 +15,10 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is ERROR. + * Subclass of {@link UndeterminedStateException} that represents all instances when + * the action performed failed due to an issue in the connection with the server. */ -public class ConnectionException extends Exception { +public class ConnectionException extends UndeterminedStateException { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java index d7127717d52..c155d695c7f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java @@ -15,8 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails before we can determine - * the state of the result, meaning the status is recorded as ERROR. + * Base exception class for all instances when the action performed fails + * before we can determine the state of the result, meaning the status + * is recorded as ERROR. */ public class UndeterminedStateException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 2e155b40afd..247424243cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,17 +14,15 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; /** *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline @@ -33,7 +31,7 @@ * messages that implement the {@link InboundMessageType} interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

@@ -44,111 +42,59 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); - - } else if (cause instanceof InternalException){ - //For an internal error, metrics should not be collected, so we log what caused this, and - //inform the ProbingStep the Prober had an internal error on this action - logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - - //As this was an internal error, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } else { - //In the case of any other kind of error, we assume it is some type of connection ERROR, - //so we treat it as such: - - status = ResponseType.ERROR; + //On UndeterminedStateException, we know the response type is an error. - logger.atInfo().log(cause.getMessage()); - finished.setSuccess(); + //Since it wasn't a success, we still log what caused the ERROR + logger.atWarning().log(cause.getMessage()); + finished.setFailure(cause); + //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } - - /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ - @VisibleForTesting - ResponseType getStatus() { - return status; - } -} - +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 69d5b7f1603..1ec4e314813 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -22,13 +22,12 @@ import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -62,27 +61,17 @@ public class WebWhoisActionHandler extends ActionHandler { /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ private final HttpRequestMessage requestMessage; - /** Default port for http. */ - private int httpPort; - - /** default port for https. */ - private int httpsPort; - @Inject public WebWhoisActionHandler( @WebWhoisProtocol Bootstrap bootstrap, @HttpWhoisProtocol Protocol httpWhoisProtocol, @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage, - @HttpWhoisProtocol int httpPort, - @HttpsWhoisProtocol int httpsPort) { + HttpRequestMessage requestMessage) { this.bootstrap = bootstrap; this.httpWhoisProtocol = httpWhoisProtocol; this.httpsWhoisProtocol = httpsWhoisProtocol; this.requestMessage = requestMessage; - this.httpPort = httpPort; - this.httpsPort = httpsPort; } @@ -93,7 +82,7 @@ public WebWhoisActionHandler( */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -112,7 +101,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -123,12 +112,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; - if (newPort == httpPort) { + if (url.getProtocol().equals(httpWhoisProtocol.name())) { newProtocol = httpWhoisProtocol; - } else if (newPort == httpsPort) { + } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -143,34 +132,38 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) .setHost(newHost) .build(); - //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); - //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..b4c01d06a8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,12 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..f1b2d6ac6a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -25,11 +25,7 @@ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { - super(version, status); - } - - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index be6c872cc3e..6e3da3f69d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,7 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline @@ -22,8 +22,9 @@ public interface OutboundMessageType { /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - public OutboundMessageType modifyMessage(String... args) throws InternalException; + OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - public String name(); + @Override + String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dd1882b5686..dab5851e8d8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,16 +14,18 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.ProbingSequence; +import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} - * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} + * in a single loop of a {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * in a {@link ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -31,17 +33,21 @@ */ public abstract class Token { - /** {@link Channel} that always starts out as null. */ + /** + * {@link Channel} that always starts out as null. Once a persistent connection + * is made (such as EPP), that channel is stored in the token and passed on to + * later steps in the sequence until a new loop begins. + */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String getHost(); + public abstract String host(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 2847e5ce0eb..bb06ee89db6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import javax.inject.Inject; import javax.inject.Named; @@ -33,42 +33,38 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final String prefix; + private final static String PREFIX = "whois.nic."; /** {@link ImmutableList} of all top level domains to be probed. */ - private final ImmutableList topLevelDomains; + private final Iterator topLevelDomainsIterator; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private int domainsIndex; + private String currentDomain; @Inject - public WebWhoisToken( - @Named("Web-WHOIS-Prefix") String prefix, - @WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { - domainsIndex = 0; - this.prefix = prefix; - this.topLevelDomains = topLevelDomains; + topLevelDomainsIterator = topLevelDomains.iterator(); + currentDomain = topLevelDomainsIterator.next(); } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - domainsIndex += 1; - domainsIndex %= topLevelDomains.size(); + currentDomain = topLevelDomainsIterator.next(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { - return original.modifyMessage(getHost()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + return original.modifyMessage(host()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String getHost() { - return prefix + topLevelDomains.get(domainsIndex); + public String host() { + return PREFIX + currentDomain; } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( { - ProbingSequence sequence = new ProbingSequence.Builder() - .addStep(firstStepBuilder) - .addStep(secondStepBuilder) - .addStep(thirdStepBuilder) - .addToken(testToken) - .setBootstrap(dummyBootstrap) - .build(); - }); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index ee38e7cdf74..7bba9d66782 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.TestUtils.dummyStep; import static google.registry.monitoring.blackbox.TestUtils.testStep; import static google.registry.testing.JUnitBackports.assertThrows; @@ -90,7 +91,7 @@ public class ProbingStepTest { /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ private void setupNewChannelToken() { - testToken = new NewChannelToken(""); + testToken = new NewChannelToken(ADDRESS_NAME); } /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ @@ -101,6 +102,7 @@ private void setupExistingChannelToken() { /** Sets up an embedded channel to contain the two handlers we created already */ private void setupChannel() { channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 161304c1f04..68bdd0bcef0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,7 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,8 +26,6 @@ import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpMessage; @@ -39,7 +37,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; -import java.net.Socket; import java.net.SocketAddress; import javax.annotation.Nullable; import javax.inject.Provider; @@ -148,15 +145,10 @@ public String toString() { } @Override - public OutboundMessageType modifyMessage(String... args) throws InternalException { + public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { message = args[0]; return this; } - - @Override - public String name() { - return "Test Message of: " + this.toString(); - } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ @@ -166,7 +158,6 @@ public static ProbingStep testStep(Protocol protocol, String testMessage, Bootst .setDuration(Duration.ZERO) .setMessageTemplate(new DuplexMessageTest(testMessage)) .setBootstrap(bootstrap) - .setAddress(address) .build(); } @@ -203,12 +194,6 @@ Bootstrap bootstrap() { return null; } - @Nullable - @Override - SocketAddress address() { - return null; - } - @Override public void accept(Token token) { future.setSuccess(token); @@ -241,7 +226,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String getHost() { + public String host() { return host; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index 67963805733..295bb809a13 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -17,12 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -37,7 +35,7 @@ public class TokenTest { private static String TEST_STARTER = "starter"; private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { @@ -49,7 +47,7 @@ public void testWebToken_MessageModificationSuccess() { try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index e170fad8b8c..3ecbdcc0d06 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -29,7 +29,7 @@ public class TestActionHandler extends ActionHandler { @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 00318ccd912..83d004d4555 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,17 +15,20 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; @@ -63,11 +66,9 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); private static final Protocol STANDARD_PROTOCOL = Protocol.builder() .setHandlerProviders(ImmutableList.of()) - .setName("test_protocol") + .setName("http") .setPersistentConnection(false) .setPort(HTTPS_PORT) .build(); @@ -79,8 +80,10 @@ public class WebWhoisActionHandlerTest { private ProbingAction probingAction; private Provider actionHandlerProvider; - private void generateLocalAddress() { - address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + private String generateLocalAddress(String addressString) { + String modifiedAddress = addressString + System.currentTimeMillis(); + address = new LocalAddress(modifiedAddress); + return modifiedAddress; } /** Creates default protocol with empty list of handlers and specified other inputs */ @@ -99,9 +102,7 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT bootstrap, STANDARD_PROTOCOL, STANDARD_PROTOCOL, - messageTemplate, - 80, - 443 + messageTemplate ); actionHandlerProvider = new TestProvider<>(actionHandler); } @@ -110,10 +111,8 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - setupProbingActionBasic( - protocol, - outboundMessage, - makeBootstrap(new NioEventLoopGroup(1))); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -122,26 +121,23 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } /**Sets up probingAction for when testing redirection */ - private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) .setHost(TARGET_HOST) - .setAddress(DEFAULT_ADDRESS) .setChannel(channel) .build(); } - private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) .setBootstrap(bootstrap) - .setHost(host) - .setAddress(address) + .setHost(addressString) .build(); } @@ -156,8 +152,6 @@ public void testBasic_responseOk() throws Exception { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseOk", 0, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); //stores future @@ -182,13 +176,12 @@ public void testBasic_responseOk() throws Exception { } @Test - public void testBasic_responseFailure() { + public void testBasic_responseFailure_badRequest() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseBad", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -210,16 +203,15 @@ public void testBasic_responseFailure() { assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testBasic_responseError() { + public void testBasic_responseFailure_badURL() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseError", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -239,9 +231,9 @@ public void testBasic_responseError() { //assesses that listener is triggered, and event is success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException); } @Test @@ -253,7 +245,6 @@ public void testBasic_redirectCloseChannel() { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("redirectHttp", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -278,44 +269,15 @@ public void testBasic_redirectCloseChannel() { } @Test - public void testBasic_redirectHost() { - //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); - HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); - - - //store future - ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); - - - channel.writeInbound(originalResponse); - - Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - } - - @Test - public void testAdvanced_responseOk() throws InternalException { + public void testAdvanced_responseOk() throws UndeterminedStateException { //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); @@ -325,22 +287,21 @@ public void testAdvanced_responseOk() throws InternalException { } @Test - public void testAdvanced_responseFailure() throws InternalException { + public void testAdvanced_responseFailure() throws UndeterminedStateException { //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); + String host = generateLocalAddress(TARGET_HOST); HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(bootstrap, msg); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + assertThrows(FailureException.class, future::syncUninterruptibly); } } From 65167cb733ec2505fe91f7bbc333de1e82aa76d1 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:48:33 -0400 Subject: [PATCH 041/337] SpotlessApply run to fix style issues --- prober/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index 77b1e2de2de..c86568e7672 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From 720d1c784776d2913022daa5f902b05ebc2f8244 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:28:40 -0400 Subject: [PATCH 042/337] Added license header and newline where appropriate. --- prober/build.gradle | 1 + .../monitoring/blackbox/ProbingAction.java | 1 - .../blackbox/handlers/ActionHandler.java | 2 +- .../monitoring/blackbox/ProbingSequenceTest.java | 14 ++++++++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 181188c5cee..478d33e1ef9 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -35,6 +35,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] + compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 67494dd5f78..a8740e21c20 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -240,7 +240,6 @@ public ProbingAction build() { InetAddress hostAddress = InetAddress.getByName(host()); address = new InetSocketAddress(hostAddress, protocol().port()); } catch (UnknownHostException e) { - System.out.println("test"); address = new LocalAddress(host()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 247424243cb..433604d6495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -97,4 +97,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } -} \ No newline at end of file +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2a8d5ebe233..8d9e45c6a66 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; From 0a4c14cce8e504d7f76eb24fed86fcf88a7572b7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 043/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/ProbingStepTest.java | 1 - .../blackbox/TestServers/WebWhoisServer.java | 3 +- .../monitoring/blackbox/TestUtils.java | 35 +------------------ .../blackbox/handlers/ConversionHandler.java | 5 ++- .../blackbox/handlers/NettyRule.java | 4 ++- 5 files changed, 10 insertions(+), 38 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 7bba9d66782..73b104ae5dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -174,7 +174,6 @@ public void testNewChannel() throws Exception { //checks that when the future is successful, we pass down the requisite token assertThat(future.get()).isEqualTo(testToken); - } @Test diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 337d755e971..e7f125bb906 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; @@ -80,7 +81,7 @@ static class RedirectHandler extends ChannelDuplexHandler { /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 68bdd0bcef0..cc8e1512fe9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; @@ -28,17 +27,13 @@ import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpMethod;; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; import java.net.SocketAddress; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -272,33 +267,5 @@ public void addToHost(String suffix) { } } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index a8506a996a9..196141bb875 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b38c1911940..1d14cf131e6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -26,6 +26,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.ProbingActionTest; +import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; @@ -54,7 +56,7 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { From 6814cb8724ddc2682bb64758f93f6fb9dbe8ed0f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 5 Aug 2019 16:16:36 -0400 Subject: [PATCH 044/337] Refactored ProbingAction to minimize number of unnecessary methods --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 4 +- .../monitoring/blackbox/ProbingAction.java | 160 ++++++++---------- .../monitoring/blackbox/ProbingStep.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 4 +- .../blackbox/handlers/ActionHandler.java | 2 +- .../handlers/WebWhoisActionHandler.java | 7 +- .../blackbox/messages/HttpRequestMessage.java | 5 +- .../blackbox/ProbingActionTest.java | 130 +++++++------- .../blackbox/ProbingSequenceTest.java | 25 ++- .../monitoring/blackbox/ProbingStepTest.java | 6 + .../monitoring/blackbox/TestUtils.java | 2 +- .../handlers/WebWhoisActionHandlerTest.java | 11 +- 13 files changed, 178 insertions(+), 183 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 307afd34d81..e12d1f0f522 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; import java.util.Set; @@ -29,7 +30,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); + Set sequences = proberComponent.sequences(); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 1db97d1b581..fb83b236b69 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -49,7 +49,7 @@ EventLoopGroup provideEventLoopGroup() { /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides @Singleton - Class provideChannelClass() { + Class provideChannelClazz() { return NioSocketChannel.class; } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @@ -77,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - Set provideAllSequences(); + Set sequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index a8740e21c20..25c3a1c17d6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -33,10 +33,8 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -69,6 +67,8 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -85,6 +85,7 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ @@ -94,108 +95,89 @@ public abstract class ProbingAction implements Callable { public abstract String host(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } - /** - * The method that performs the work of the actual action. + * Performs the work of the actual action * - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ *

First, checks if channel is active by setting a listener to perform the bulk of the work + * when the connection future is successful.

+ * + *

Once the connection is successful, we establish which of the handlers in the pipeline is + * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when + * we receive an expected response from the server.

+ * + *

Next, we set a timer set to a specified delay. After the delay has passed, we send the + * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, + * we inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - - //ChannelPromise that we use to inform ProbingStep when we are finished. - ChannelPromise finished = channel().newPromise(); - - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - - return finished; - } /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws UndeterminedStateException { + public ChannelFuture call() { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); + + //Ensures channel has been set up with connection future as an attribute + checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + //When connection is established call super.call and set returned listener to success channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { + (ChannelFuture connectionFuture) -> { + if (connectionFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); + ActionHandler actionHandler; + try { + actionHandler = channel().pipeline().get(ActionHandler.class); + } catch (ClassCastException e) { + //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); + } + + ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> { + if (future.isSuccess()) { + finished.setSuccess(); + } else { + finished.setFailure(future.cause()); + } + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) { + logger.atInfo() + .log("Closed stale channel. Moving on to next ProbingStep"); + } else { + logger.atWarning() + .log( + "Could not close channel. Stale connection still exists."); + } + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); } else { //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( + logger.atSevere().withCause(connectionFuture.cause()).log( "Cannot connect to relay channel for %s channel: %s.", protocol().name(), this.channel()); ChannelFuture unusedFuture = channel().close(); @@ -228,7 +210,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract Protocol protocol(); - abstract Optional channel(); + abstract Channel channel(); abstract String host(); @@ -243,11 +225,11 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { + if (channel() == null) { bootstrap.handler( new ChannelInitializer() { @Override diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index ca980100067..3df536a9478 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -135,7 +135,7 @@ public void accept(Token token) { try { //call the generated action future = currentAction.call(); - } catch(UndeterminedStateException e) { + } catch(Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index c5e41fea38b..2e640338511 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -184,10 +184,10 @@ static SslClientInitializer provideSslClientInitializer(SslPro @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClass){ + Class channelClazz){ return new Bootstrap() .group(eventLoopGroup) - .channel(channelClass); + .channel(channelClazz); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 433604d6495..ab628ed064f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -46,7 +46,7 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler testHandlerProvider = new TestProvider<>(testHandler); private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - private ProbingAction newChannelAction; - private ProbingAction existingChannelAction; - private EmbeddedChannel channel; - private Protocol protocol; - /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** Sets up a {@link Protocol} corresponding to when a new connection is created */ - private void setupNewChannelProtocol() { - protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - } - /** Sets up a {@link Protocol} corresponding to when a new connection exists */ - private void setupExistingChannelProtocol() { - protocol = Protocol.builder() + + + + @Test + public void testBehavior_existingChannel() throws UndeterminedStateException { + //setup + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up a Protocol corresponding to when a connection exists. + Protocol protocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) .build(); - } - - /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ - private void setupNewChannelAction() { - newChannelAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - } - - private void setupChannel() { - channel = new EmbeddedChannel(); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ - private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ProbingAction.builder() + // Sets up a ProbingAction that creates a channel using test specified attributes. + ProbingAction action = ProbingAction.builder() .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) .setHost("") .build(); - } - - @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { - //setup - setupChannel(); - setupExistingChannelProtocol(); - channel.pipeline().addLast(conversionHandler); - channel.pipeline().addLast(testHandler); - setupExistingChannelAction(channel); + //tests main function of ProbingAction + ChannelFuture future = action.call(); - ChannelFuture future = existingChannelAction.call(); - - //Ensures that we pass in the right message to the channel and haven't marked the future as success yet - Object msg = channel.readOutbound(); + //Obtains the outboundMessage passed through pipeline after delay + Object msg = null; + while (msg == null) { + msg = channel.readOutbound(); + } + //tests the passed message is exactly what we expect assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - assertThat(response).isEqualTo(TEST_MESSAGE); - assertThat(future.isSuccess()).isFalse(); + String request = ((ByteBuf) msg).toString(UTF_8); + assertThat(request).isEqualTo(TEST_MESSAGE); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -158,18 +122,40 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { @Test public void testSuccess_newChannel() throws Exception { //setup - setupNewChannelProtocol(); + + LocalAddress address = new LocalAddress(ADDRESS_NAME); + Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + // Sets up a Protocol corresponding to when a new connection is created. + Protocol protocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) + .build(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - setupNewChannelAction(); - ChannelFuture future = newChannelAction.call(); + + // Sets up a ProbingAction with existing channel using test specified attributes. + ProbingAction action = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) + .build(); + + //tests main function of ProbingAction + ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.sync(); + future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()); + assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 8d9e45c6a66..e5f91a300d6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -18,27 +18,44 @@ import static google.registry.testing.JUnitBackports.assertThrows; import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.TestUtils.TestToken; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import java.net.SocketAddress; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; @RunWith(JUnit4.class) public class ProbingSequenceTest { private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new ProbingSequenceTestToken(); + private Token testToken = new TestToken("") { + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + }; + private void setupMock(ProbingStep mock, ProbingStep nextStep) { + Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + } /** * Custom {@link ProbingStep} subclass that acts as a mock * step, so we can test how well {@link ProbingSequence} builds * a linked list of {@link ProbingStep}s from their {@link Builder}s. */ + private static class TestStep extends ProbingStep { private String marker; @@ -92,9 +109,9 @@ public void specialAccept(Token token) { @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 73b104ae5dc..256eeb0b29d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -45,6 +45,7 @@ import javax.inject.Provider; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ public class ProbingStepTest { @@ -191,6 +192,11 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); + Object msg = channel.readOutbound(); + + while (msg == null) { + msg = channel.readOutbound(); + } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index cc8e1512fe9..ef9926a7620 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -204,7 +204,7 @@ public String toString() { } /** Basic outline for {@link Token} instances to be used in tests */ - private static abstract class TestToken extends Token { + static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 83d004d4555..f6123045683 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -41,7 +41,6 @@ import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; import org.joda.time.Duration; @@ -155,7 +154,8 @@ public void testBasic_responseOk() throws Exception { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -185,7 +185,8 @@ public void testBasic_responseFailure_badRequest() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); @@ -215,7 +216,7 @@ public void testBasic_responseFailure_badURL() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -248,7 +249,7 @@ public void testBasic_redirectCloseChannel() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early From fba1688594b042f8a6fd729160c0e4fb462d7bf7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 15:45:32 -0400 Subject: [PATCH 045/337] Modified tests for WebWhois according to changes suggested by laijiang. --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 2 - .../monitoring/blackbox/ProbingAction.java | 1 - .../monitoring/blackbox/WebWhoisModule.java | 10 +- .../blackbox/ProbingActionTest.java | 20 +- .../blackbox/ProbingSequenceTest.java | 120 ++++------- .../monitoring/blackbox/ProbingStepTest.java | 187 ++++++++--------- .../blackbox/TestServers/TestServer.java | 38 ---- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 142 +------------ .../monitoring/blackbox/TokenTest.java | 59 ------ .../blackbox/handlers/ConversionHandler.java | 6 +- .../blackbox/handlers/NettyRule.java | 46 +++- .../handlers/SslClientInitializerTest.java | 5 - .../blackbox/handlers/TestActionHandler.java | 7 +- .../handlers/WebWhoisActionHandlerTest.java | 197 +++++++----------- .../blackbox/messages/TestMessage.java | 4 + .../blackbox/tokens/WebWhoisTokenTest.java | 2 + 18 files changed, 266 insertions(+), 589 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index e12d1f0f522..5ca423c29cc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -30,7 +29,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.sequences(); + ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index fb83b236b69..f9db4865f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,11 +14,9 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 25c3a1c17d6..0265390fafe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -138,7 +138,6 @@ public ChannelFuture call() { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); timer.newTimeout(timeout -> { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 2e640338511..de041afad38 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,14 +17,11 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -33,10 +30,7 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index b5d8f7599c4..ec5ee5d77ec 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,17 +20,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -39,9 +37,9 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; import javax.inject.Provider; import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,10 +72,9 @@ public class ProbingActionTest { public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - + @Ignore @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { + public void testBehavior_existingChannel() { //setup EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -95,7 +92,7 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost("") .build(); @@ -112,6 +109,9 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { String request = ((ByteBuf) msg).toString(UTF_8); assertThat(request).isEqualTo(TEST_MESSAGE); + // Ensures that we haven't marked future as done until response is received. + assertThat(future.isDone()).isFalse(); + //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); assertThat(future.isSuccess()).isTrue(); @@ -143,7 +143,7 @@ public void testSuccess_newChannel() throws Exception { .setBootstrap(bootstrap) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost(ADDRESS_NAME) .build(); @@ -151,7 +151,7 @@ public void testSuccess_newChannel() throws Exception { ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index e5f91a300d6..5c4452df7b3 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -15,17 +15,11 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; -import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; -import google.registry.monitoring.blackbox.TestUtils.TestToken; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import java.net.SocketAddress; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,85 +27,31 @@ @RunWith(JUnit4.class) public class ProbingSequenceTest { - private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new TestToken("") { - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - }; - - private void setupMock(ProbingStep mock, ProbingStep nextStep) { - Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + private ProbingStep setupMock() { + ProbingStep mock = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(mock).nextStep(); + return mock; } - /** - * Custom {@link ProbingStep} subclass that acts as a mock - * step, so we can test how well {@link ProbingSequence} builds - * a linked list of {@link ProbingStep}s from their {@link Builder}s. - */ - - private static class TestStep extends ProbingStep { - private String marker; - - /** We implement all abstract methods to simply return null, as we have no use for them here. */ - @Override - Duration duration() { - return null; - } - @Override - Protocol protocol() { - return null; - } + private static class Wrapper { - @Override - OutboundMessageType messageTemplate() { - return null; - } + T data; - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ - @Override - Bootstrap bootstrap() { - return null; - } - - public TestStep(String marker) { - this.marker = marker; - } - - /** - * On a call to accept, we modify the token to reflect what the current step is, so we can get - * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated - * in order. - */ - @Override - public void accept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - if (!isLastStep) { - nextStep().accept(token); - } else { - ((TestStep)nextStep()).specialAccept(token); - } - } - - /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ - public void specialAccept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - return; + public Wrapper(T data) { + this.data = data; } } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = Mockito.mock(ProbingStep.class); - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) @@ -119,16 +59,25 @@ public void testSequenceBasicConstruction_Success() { .addStep(thirdStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(thirdStep); + assertThat(thirdStep.nextStep()).isEqualTo(firstStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); + assertThat(wrapper.data).isTrue(); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(thirdStep) @@ -137,9 +86,16 @@ public void testSequenceAdvancedConstruction_Success() { .addStep(firstStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(firstStep); + assertThat(thirdStep.nextStep()).isEqualTo(secondStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); + assertThat(wrapper.data).isTrue(); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 256eeb0b29d..91a113940e8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,18 +11,19 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.TestUtils.dummyStep; -import static google.registry.monitoring.blackbox.TestUtils.testStep; -import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; import google.registry.monitoring.blackbox.TestUtils.TestProvider; @@ -30,19 +31,20 @@ import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; +import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; @@ -51,18 +53,18 @@ public class ProbingStepTest { /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final static String ADDRESS_NAME = "TEST_ADDRESS"; + private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final static int PROTOCOL_PORT = 0; + private final static String TEST_MESSAGE = "TEST_MESSAGE"; + private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -73,117 +75,108 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(ADDRESS_NAME); + /** + * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} + * is called, it just marks the supplied future as succeeded, returning the requisite token. + */ + private ProbingStep dummyStep() { + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(dummyStep).nextStep(); + return dummyStep; } - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); - dummyStep = dummyStep(eventLoopGroup); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - } + @Test + public void testNewChannel() throws Exception { + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() + // Sets up Protocol for when we create a new channel. + Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); - } - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) .build(); - } - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - //there should be no next step - assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); - } + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); - @Test - public void testNewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + //Set up blackbox server that receives our messages then echoes them back to us + nettyRule.setUpServer(address); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); + verify(dummyStep, times(1)).accept(any(Token.class)); } + @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupChannel(); - setupExistingChannelToken(); + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); + + // Sets up Protocol for when a channel already exists. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) + .build(); + + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) + .build(); + + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + + // Sets up an embedded channel to contain the two handlers we created already. + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + + //Assures that the channel has a succeeded connectionFuture. + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. + Token testToken = new ExistingChannelToken(channel, ""); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -200,17 +193,13 @@ public void testWithSequence_ExistingChannel() throws Exception { //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); + //At this point, we should have received the message, so the future obtained should be marked + // as a success + verify(dummyStep, times(1)).accept(any(Token.class)); - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index a4474b6b8b5..12e25a6bc6c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -14,24 +14,16 @@ package google.registry.monitoring.blackbox.TestServers; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; - import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform @@ -65,35 +57,5 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index e7f125bb906..4da75b31c25 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -74,7 +75,7 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends ChannelDuplexHandler { + static class RedirectHandler extends SimpleChannelInboundHandler { private String redirectInput; private String destinationInput; @@ -90,8 +91,7 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - HttpRequest request = (HttpRequest) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index ef9926a7620..2567a7cc155 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,42 +16,24 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMethod;; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.concurrent.DefaultPromise; -import java.net.SocketAddress; import javax.inject.Provider; -import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { - static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -76,33 +58,13 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); + response.headers().set("content-type", "text/plain"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); return response; } @@ -121,88 +83,6 @@ public E get() { } } - /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ - public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { - - String message; - - public DuplexMessageTest() { - message = ""; - } - - public DuplexMessageTest(String msg) { - message = msg; - } - - @Override - public String toString() { - return message; - } - - @Override - public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { - message = args[0]; - return this; - } - } - - /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .build(); - - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); - } - - /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { - private DefaultPromise future; - - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; - } - - @Override - public void accept(Token token) { - future.setSuccess(token); - } - public DefaultPromise getFuture() { - return future; - } - - @Override - public String toString() { - return "Dummy Step"; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; @@ -251,21 +131,5 @@ public Channel channel() { return channel; } } - - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java deleted file mode 100644 index 295bb809a13..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) - */ -@RunWith(JUnit4.class) -public class TokenTest { - - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - - public Token webToken = new WebWhoisToken(TEST_DOMAINS); - - @Test - public void testWebToken_MessageModificationSuccess() { - //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); - - //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { - throw new RuntimeException(e); - } - - - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 196141bb875..c9d337d6ad8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -32,7 +32,7 @@ * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +40,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 1d14cf131e6..86b54d9a07d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -25,14 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -44,7 +41,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -55,7 +51,7 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + *

Code based on and almost identical to {@code NettyRule} in the proxy. * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -83,10 +79,12 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + ImmutableList.builder().add(handlers).add(echoHandler).build()); } /** Sets up a client channel connecting to the give local address. */ @@ -124,7 +122,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertThatCustomWorks(String message) throws Exception { + public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -165,6 +163,38 @@ ThrowableSubject assertThatClientRootCause() { } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** + * Saves any inbound error as the cause of the promise failure. + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 83c8e132f07..523fb228752 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -22,12 +22,7 @@ import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 3ecbdcc0d06..95b06e623d1 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -25,17 +25,16 @@ */ public class TestActionHandler extends ActionHandler { - private String receivedMessage; + private InboundMessageType receivedMessage; @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage.toString(); + receivedMessage = inboundMessage; super.channelRead0(ctx, inboundMessage); } - @Override - public String toString() { + public InboundMessageType getResponse() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index f6123045683..d9d1a45ac6e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -20,7 +20,6 @@ import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; -import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; @@ -28,13 +27,11 @@ import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; @@ -56,6 +53,7 @@ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -65,11 +63,12 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of()) + private final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( + null, null, null, null)))) .setName("http") .setPersistentConnection(false) - .setPort(HTTPS_PORT) + .setPort(HTTP_PORT) .build(); @@ -78,14 +77,13 @@ public class WebWhoisActionHandlerTest { private ActionHandler actionHandler; private ProbingAction probingAction; private Provider actionHandlerProvider; + private Protocol initialProtocol; + private HttpRequestMessage msg; - private String generateLocalAddress(String addressString) { - String modifiedAddress = addressString + System.currentTimeMillis(); - address = new LocalAddress(modifiedAddress); - return modifiedAddress; - } - /** Creates default protocol with empty list of handlers and specified other inputs */ + /** + * Creates default protocol with empty list of handlers and specified other inputs + */ private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() .setName(name) @@ -95,7 +93,9 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect .build(); } - /** Initializes new WebWhoisActionHandler */ + /** + * Initializes new WebWhoisActionHandler + */ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, @@ -106,12 +106,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT actionHandlerProvider = new TestProvider<>(actionHandler); } - /** Sets up testing channel with requisite attributes */ + /** + * Sets up testing channel with requisite attributes + */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -119,18 +120,9 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .group(group) .channel(LocalChannel.class); } - /**Sets up probingAction for when testing redirection */ - private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setHost(TARGET_HOST) - .setChannel(channel) - .build(); - } - private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { + private void setupProbingActionWithoutChannel(Protocol protocol, + HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) @@ -140,170 +132,123 @@ private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMess .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + private void setupLocalServer(String redirectInput, String destinationInput, + EventLoopGroup group) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testBasic_responseOk() throws Exception { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { + msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, true); + initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + } + + @Test + public void testBasic_responseOk() { + //setup + setup("", null, true); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure_badRequest() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseBad", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage( + makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same assertThat(future.cause() instanceof FailureException).isTrue(); } - @Test - public void testBasic_responseFailure_badURL() { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseError", 0, true); - setupChannel(initialProtocol, msg); - - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, and event is success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); - } @Test - public void testBasic_redirectCloseChannel() { + public void testBasic_responseFailure_badURL() { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - //checks that future has not been set to successful or a failure - assertThat(testPromise.isSuccess()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - + //assesses that listener is triggered, and event is success + assertThat(future.isDone()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + //ensures Protocol is the same + assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_responseOk() throws UndeterminedStateException { - //setup + public void testAdvanced_redirect() { + // Sets up EventLoopGroup with 1 thread to be blocking. EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + // Sets up embedded channel. + setup("", makeBootstrap(group), false); + setupChannel(initialProtocol, msg); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); - } + // Initializes LocalAddress with unique String. + String host = TARGET_HOST + System.currentTimeMillis(); + address = new LocalAddress(host); - @Test - public void testAdvanced_responseFailure() throws UndeterminedStateException { - //setup - EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); + //stores future + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); + + // Sets up the local server that the handler will be redirected to. setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + FullHttpResponse response = + new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, + HTTP_REDIRECT + host, true, false)); + + //checks that future has not been set to successful or a failure + assertThat(future.isDone()).isFalse(); + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); //assesses that we successfully received good response and protocol is unchanged - assertThrows(FailureException.class, future::syncUninterruptibly); + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index 922c3052bda..c31a9d336bd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,6 +24,10 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; + public TestMessage() { + this(""); + } + public TestMessage(String msg) { message = msg; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index 9a3e755364b..bf5cfc45652 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -19,6 +19,8 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; From 95cea037d1d8805768adbc70d1fead179c0449bf Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 16:42:43 -0400 Subject: [PATCH 046/337] Removed TestProvider from TestUtils. --- .../blackbox/ProbingActionTest.java | 7 ++-- .../monitoring/blackbox/ProbingStepTest.java | 11 ++---- .../blackbox/TestServers/TestServer.java | 3 -- .../monitoring/blackbox/TestUtils.java | 17 -------- .../handlers/WebWhoisActionHandlerTest.java | 39 +++++++------------ .../blackbox/messages/TestMessage.java | 4 -- 6 files changed, 20 insertions(+), 61 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index ec5ee5d77ec..f7857dd80f9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -64,8 +63,8 @@ public class ProbingActionTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + private Provider testHandlerProvider = () -> testHandler; + private Provider conversionHandlerProvider = () -> conversionHandler; /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -156,7 +155,7 @@ public void testSuccess_newChannel() throws Exception { future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 91a113940e8..1f09dd13553 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -90,9 +89,8 @@ private ProbingStep dummyStep() { @Test public void testNewChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when we create a new channel. Protocol testProtocol = Protocol.builder() @@ -142,9 +140,8 @@ public void testNewChannel() throws Exception { @Test public void testWithSequence_ExistingChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when a channel already exists. Protocol testProtocol = Protocol.builder() diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 12e25a6bc6c..46615a506fb 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -29,15 +29,12 @@ * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { - private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - this.localAddress = localAddress; - //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 2567a7cc155..50c60d9fc52 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -21,7 +21,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -29,7 +28,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Provider; /** Utility class for various helper methods used in testing. */ public class TestUtils { @@ -68,21 +66,6 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ - public static class TestProvider implements Provider { - - private E obj; - - public TestProvider(E obj) { - this.obj = obj; - } - - @Override - public E get() { - return obj; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index d9d1a45ac6e..cd85dd08df8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -22,10 +22,8 @@ import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; @@ -64,18 +62,16 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( - null, null, null, null)))) + .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( + null, null, null, null))) .setName("http") .setPersistentConnection(false) .setPort(HTTP_PORT) .build(); - private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; - private ProbingAction probingAction; private Provider actionHandlerProvider; private Protocol initialProtocol; private HttpRequestMessage msg; @@ -103,13 +99,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT STANDARD_PROTOCOL, messageTemplate ); - actionHandlerProvider = new TestProvider<>(actionHandler); + actionHandlerProvider = () -> actionHandler; } /** * Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + private void setupChannel(Protocol protocol) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -121,19 +117,8 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } - private void setupProbingActionWithoutChannel(Protocol protocol, - HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(addressString) - .build(); - } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group) { + EventLoopGroup group, LocalAddress address) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } @@ -148,7 +133,9 @@ private void setup(String hostName, Bootstrap bootstrap, boolean persistentConne public void testBasic_responseOk() { //setup setup("", null, true); - setupChannel(initialProtocol, msg); + + setupChannel(initialProtocol); + //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); @@ -168,7 +155,7 @@ public void testBasic_responseOk() { public void testBasic_responseFailure_badRequest() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -194,7 +181,7 @@ public void testBasic_responseFailure_badRequest() { public void testBasic_responseFailure_badURL() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -223,18 +210,18 @@ public void testAdvanced_redirect() { // Sets up embedded channel. setup("", makeBootstrap(group), false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); // Initializes LocalAddress with unique String. String host = TARGET_HOST + System.currentTimeMillis(); - address = new LocalAddress(host); + LocalAddress address = new LocalAddress(host); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group); + setupLocalServer("", host, group, address); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index c31a9d336bd..922c3052bda 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,10 +24,6 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; - public TestMessage() { - this(""); - } - public TestMessage(String msg) { message = msg; } From 73f346173860ae1f376ba9b5806cd865c256117b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 047/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 2 +- .../google/registry/xjc/package-info.java | 2 +- prober/build.gradle | 5 - .../monitoring/blackbox/NewChannelAction.java | 136 +++++++++ .../registry/monitoring/blackbox/Prober.java | 19 +- .../monitoring/blackbox/ProbingAction.java | 265 ++++++------------ .../handlers/ServerSideException.java | 15 + .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 117 +++----- .../blackbox/messages/HttpRequestMessage.java | 63 +---- .../messages/HttpResponseMessage.java | 44 +-- .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 15 files changed, 320 insertions(+), 365 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/prober/build.gradle b/prober/build.gradle index 478d33e1ef9..d0ac4ff3b51 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -20,8 +20,6 @@ dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] @@ -33,9 +31,6 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..0ba3a0c22be --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 5ca423c29cc..333330207f1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,26 +14,17 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 0265390fafe..2441debb12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,27 +14,14 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -47,7 +34,7 @@ import javax.inject.Provider; /** - * AutoValue class that represents action generated by {@link ProbingStep} + *Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -57,27 +44,36 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

*/ -@AutoValue + public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; + } /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); + /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -85,177 +81,92 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ - @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); - /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> finished.setSuccess(), + future -> { + if (!protocol().persistentConnection()) { + + //If we created a new channel for this action, close the connection to the channel + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } /** - * Performs the work of the actual action + * The method that sends the {@code outboundMessage} down the channel pipeline * - *

First, checks if channel is active by setting a listener to perform the bulk of the work - * when the connection future is successful.

- * - *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

- * - *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

- * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. + * @return future that denotes when the action has been successfully performed */ - - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override public ChannelFuture call() { - //ChannelPromise that we return - ChannelPromise finished = channel().newPromise(); - //Ensures channel has been set up with connection future as an attribute - checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); - - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture connectionFuture) -> { - if (connectionFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - - ActionHandler actionHandler; - try { - actionHandler = channel().pipeline().get(ActionHandler.class); - } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); - - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> { - if (future.isSuccess()) { - finished.setSuccess(); - } else { - finished.setFailure(future.cause()); - } - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) { - logger.atInfo() - .log("Closed stale channel. Moving on to next ProbingStep"); - } else { - logger.atWarning() - .log( - "Could not close channel. Stale connection still exists."); - } - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(connectionFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ - @AutoValue.Builder - public abstract static class Builder { - private Bootstrap bootstrap; - - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); } - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setHost(String value); - - public abstract Builder setChannel(Channel channel); - - abstract Protocol protocol(); + //ChannelPromise that we use to inform ProbingStep when we are finished. + ChannelPromise finished = channel().newPromise(); - abstract Channel channel(); + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } - abstract String host(); + return finished; + } - abstract ProbingAction autoBuild(); + public abstract static class Builder, P extends ProbingAction> { - public ProbingAction build() { - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - address = new LocalAddress(host()); - } + public abstract B delay(Duration value); - checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); - //If a channel is supplied, nothing is needed to be done + public abstract B outboundMessage(OutboundMessageType value); - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel() == null) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); + public abstract B protocol(Protocol value); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); + public abstract B host(String value); - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } + public abstract B path(String value); - //now we can actually build the ProbingAction - return autoBuild(); - } - } + public abstract P build(); - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); } /** @@ -265,27 +176,11 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - private static void addHandlers( + static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { channelPipeline.addLast(handlerProvider.get()); } } - - - - @Override - public String toString() { - return String.format( - "ProbingAction with delay: %d\n" + - "outboundMessage: %s\n" + - "protocol: %s\n" + - "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index 919006592ea..ac844ac99df 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,8 +15,7 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -90,8 +89,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - String host = channel.attr(REMOTE_ADDRESS_KEY).get(); + ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); + Protocol protocol = action.protocol(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -104,7 +103,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), host, protocol.port()); + .newHandler(channel.alloc(), action.host(), protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 34eac2a0118..21010f0e887 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,23 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -47,53 +48,30 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ - private final Bootstrap bootstrap; - - /** {@link Protocol} for when redirected to http endpoint. */ - private final Protocol httpWhoisProtocol; - - /** {@link Protocol} for when redirected to https endpoint. */ - private final Protocol httpsWhoisProtocol; - - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } + public WebWhoisActionHandler() {} /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { + throws ServerSideException { HttpResponseMessage response = (HttpResponseMessage) msg; + if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - //On success, we always pass message to ActionHandler's channelRead0 method. - super.channelRead0(ctx, msg); + finished.setSuccess(); + + logger.atInfo().log("Response Received: " + response); - } else if (response.headers().get("location") != null) { + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { //Obtain url to be redirected to URL url; @@ -101,68 +79,55 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); + int newPort = url.getDefaultPort(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, url.getDefaultPort(), newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException("Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); - } + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) .build(); + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } + logger.atInfo().log("Successfully Closed Connection"); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE + finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 5e9300d0f34..3fb8c187ad9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -19,28 +5,19 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; -/** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. - * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + @Override @@ -49,33 +26,15 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } - - /** Modifies headers to reflect new host and new path if applicable. */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) - setUri(args[1]); - - return this; + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + ByteBuf buf = request.content(); + if (buf == null) { + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - throw new IllegalArgumentException( - String.format( - "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + args, args.length)); + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - } - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index f1b2d6ac6a7..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,19 +6,33 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} - */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { + super(version, status); + } + + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); + + return finalResponse; } + + + } diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From fa9030e271b8c7a41c6c7dd54431c6b37cff70ce Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:58:52 -0400 Subject: [PATCH 048/337] Fixed changes suggested by CydeWeys --- prober/build.gradle | 37 +-- .../monitoring/blackbox/Protocol.java | 87 +++++-- .../blackbox/exceptions/FailureException.java | 15 +- .../blackbox/handlers/ActionHandler.java | 91 +++---- .../handlers/WebWhoisActionHandlerTest.java | 222 ++++++++---------- 5 files changed, 224 insertions(+), 228 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index d0ac4ff3b51..259b093e35e 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,30 +16,35 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 624f08fd4e9..371b3c3e8d7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,28 +16,81 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; import javax.inject.Provider; /** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. + * Protocol Class packages all static variables necessary for a certain type of connection + * Both the host and the path can be changed for the same protocol + * Mainly packages the handlers necessary for the requisite channel pipeline */ @AutoValue public abstract class Protocol { - /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ - public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + + /** + * Default names associated with each protocol + */ + final static String EPP_PROTOCOL_NAME = "EPP"; + final static String DNS_PROTOCOL_NAME = "DNS"; + final static String WHOIS_PROTOCOL_NAME = "WHOIS"; + final static String RDAP_PROTOCOL_NAME = "RDAP"; + + private String host; + private String path = ""; + private ProbingAction probingAction; + + /** Setter method for Protocol's host*/ + public Protocol host(String host) { + this.host = host; + return this; + } + + /** Getter method for Protocol's host*/ + public String host() { + return host; + } + + /** Setter method for Protocol's path*/ + public Protocol path(String path) { + this.path = path; + return this; + } + + /** Getter method for Protocol's path*/ + public String path() { + return path; + } + /** Setter method for Protocol's ProbingAction parent*/ + public Protocol probingAction(ProbingAction probingAction) { + this.probingAction = probingAction; + return this; + } + + /** Getter method for Protocol's path*/ + public ProbingAction probingAction() { + return probingAction; + } + + /** If connection associated with Protocol is persistent, which is only EPP */ + public boolean persistentConnection() { + return name() == EPP_PROTOCOL_NAME; + } + + /** Protocol Name */ public abstract String name(); + /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - abstract ImmutableList> handlerProviders(); + public abstract ImmutableList> handlerProviders(); - /** Boolean that notes if connection associated with Protocol is persistent.*/ - abstract boolean persistentConnection(); + + public abstract Builder toBuilder(); public static Builder builder() { return new AutoValue_Protocol.Builder(); @@ -47,25 +100,13 @@ public static Builder builder() { @AutoValue.Builder public abstract static class Builder { - public abstract Builder setName(String value); - - public abstract Builder setPort(int num); + public abstract Builder name(String value); - public abstract Builder setHandlerProviders(ImmutableList> providers); + public abstract Builder port(int num); - public abstract Builder setPersistentConnection(boolean value); + public abstract Builder handlerProviders(ImmutableList> providers); public abstract Protocol build(); } - - @Override - public String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); - } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 36687e7ac82..9f716bb2589 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,18 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.exceptions; +package google.registry.monitoring.blackbox; -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class FailureException extends Exception { - - public FailureException(String msg) { - super(msg); - } - - public FailureException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index ab628ed064f..3fa60cd844a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,86 +15,69 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; +import com.google.common.flogger.StackSize; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.HttpResponse; +import java.util.function.Function; +import javax.inject.Inject; /** - *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

- * - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} - * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

- * - *

Subclasses specify further work to be done for specific kinds of channel pipelines.

+ * @param Generic Type of Inbound Message + * @param Generic Type of Outbound Message + * Abstract class that tells sends message down pipeline and + * and tells listeners to move on when the message is received. */ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +public abstract class ActionHandler extends SimpleChannelInboundHandler + implements Function { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link ChannelPromise} that informs {@link ProbingAction} if response has been received. */ - private ChannelPromise finished; + protected ChannelPromise finished; + private Channel channel; + - /** Returns initialized {@link ChannelPromise} to {@link ProbingAction}.*/ - public ChannelFuture getFinishedFuture() { + /** returns ChannelPromise for when inbound message is recieved + * a + * @param outboundMessage + * @return + */ + @Override + public ChannelFuture apply(O outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + + channel.writeAndFlush(outboundMessage); return finished; + + } + + public void resetFuture() { + finished = channel.newPromise(); } - /** Initializes {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { - // Once handler is added to channel pipeline, initialize channel and future for this handler + //Once handler is added to channel pipeline, initialize channel and future for this handler + + channel = ctx.channel(); finished = ctx.newPromise(); } - /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ + //Only purpose of Handler is to mark future as a success finished.setSuccess(); } - /** - * Logs the channel and pipeline that caused error, closes channel, then informs - * {@link ProbingAction} listeners of error. - */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atWarning().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); - - if (cause instanceof FailureException) { - //On FailureException, we know the response is a failure. - - //Since it wasn't a success, we still want to log to see what caused the FAILURE - logger.atInfo().log(cause.getMessage()); - - //As always, inform the ProbingStep that we successfully completed this action - finished.setFailure(cause); - - } else { - //On UndeterminedStateException, we know the response type is an error. - - //Since it wasn't a success, we still log what caused the ERROR - logger.atWarning().log(cause.getMessage()); - finished.setFailure(cause); - - //As this was an ERROR in performing the action, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } + logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } } + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index cd85dd08df8..63bb2cf5b53 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,43 +15,34 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelPromise; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@link WebWhoisActionHandler}. - * - *

Attempts to test how well {@link WebWhoisActionHandler} works - * when responding to all possible types of responses

- */ +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -59,183 +50,172 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; - private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( - null, null, null, null))) - .setName("http") - .setPersistentConnection(false) - .setPort(HTTP_PORT) - .build(); private EmbeddedChannel channel; private ActionHandler actionHandler; - private Provider actionHandlerProvider; - private Protocol initialProtocol; - private HttpRequestMessage msg; - - /** - * Creates default protocol with empty list of handlers and specified other inputs - */ - private Protocol createProtocol(String name, int port, boolean persistentConnection) { + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() - .setName(name) - .setPort(port) - .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) - .setPersistentConnection(persistentConnection) - .build(); + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); } - /** - * Initializes new WebWhoisActionHandler - */ - private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { - actionHandler = new WebWhoisActionHandler( - bootstrap, - STANDARD_PROTOCOL, - STANDARD_PROTOCOL, - messageTemplate - ); - actionHandlerProvider = () -> actionHandler; + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); } - /** - * Sets up testing channel with requisite attributes - */ + /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol) { + setupActionHandler(); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - private Bootstrap makeBootstrap(EventLoopGroup group) { - return new Bootstrap() - .group(group) - .channel(LocalChannel.class); + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group, LocalAddress address) { - WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); } - private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { - msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); - setupActionHandler(bootstrap, msg); - initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; } + @Test - public void testBasic_responseOk() { + public void testSuccess_responseOk() { //setup - setup("", null, true); - + Protocol initialProtocol = createProtocol("responseOk", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badRequest() { + public void testSuccess_responseBad() { //setup - setup("", null, false); + Protocol initialProtocol = createProtocol("responseBad", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage( - makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(future.isDone()).isTrue(); + assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badURL() { + public void testSuccess_redirectCloseChannel() { //setup - setup("", null, false); - setupChannel(initialProtocol); + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, and event is success - assertThat(future.isDone()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_redirect() { - // Sets up EventLoopGroup with 1 thread to be blocking. - EventLoopGroup group = new NioEventLoopGroup(1); - - // Sets up embedded channel. - setup("", makeBootstrap(group), false); - setupChannel(initialProtocol); - - // Initializes LocalAddress with unique String. - String host = TARGET_HOST + System.currentTimeMillis(); - LocalAddress address = new LocalAddress(host); + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group, address); - FullHttpResponse response = - new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + host, true, false)); + channel.writeInbound(originalResponse); - //checks that future has not been set to successful or a failure - assertThat(future.isDone()).isFalse(); + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); - channel.writeInbound(response); + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } + } From bd28369a230c1d455d2114cbf0b923ff13c75fe6 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 049/337] Added missing license headers and JavaDoc --- .../handlers/ServerSideException.java | 16 ++++++- .../blackbox/messages/HttpRequestMessage.java | 45 ++++++++++++++----- .../messages/HttpResponseMessage.java | 32 ++++++++++--- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java index 5d3addb920e..441062a9e7b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; /** @@ -12,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 3fb8c187ad9..8fbb55c6339 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,13 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} + * (but needs to implement {@link OutboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion + * from {@link FullHttpRequest} to its type

+ */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +35,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,15 +42,22 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - if (buf == null) { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //creates message based on content found in original request + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //stores headers from request in finalRequest + request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); + + return finalRequest; + + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..776e7de0824 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,11 +1,33 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} + * (but needs to implement {@link InboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion + * from {@link FullHttpResponse} to its type

+ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -17,22 +39,20 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } + /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); + //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + //stores headers from response in finalResponse + response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); return finalResponse; } - - - } From de578349ed5b4b27583b97f3ac36129366017be3 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 050/337] Minor fix in NewChannelAction JavaDoc --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..1e7578d5679 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; - import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -28,8 +27,7 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) */ @AutoValue public abstract class NewChannelAction extends ProbingAction { From 15cd602c233753f7fd3d717bf82fb07651e94f7a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 13:33:23 -0400 Subject: [PATCH 051/337] Minor Style Fix --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 ---- .../java/google/registry/monitoring/blackbox/Protocol.java | 1 - .../registry/monitoring/blackbox/handlers/ActionHandler.java | 1 - .../monitoring/blackbox/handlers/WebWhoisActionHandler.java | 2 -- 4 files changed, 8 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..84cf75492f2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -52,7 +52,6 @@ public Channel channel() { return this.channel; } - @Override public abstract Builder toBuilder(); @@ -120,7 +119,6 @@ public static NewChannelAction.Builder builder() return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -129,6 +127,4 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 371b3c3e8d7..4b0727229c1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -109,4 +109,3 @@ public abstract static class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 3fa60cd844a..503d211b324 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -80,4 +80,3 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 21010f0e887..5b77461cd8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -131,7 +131,5 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } } - - } From 4c845598f9095350a16766b1cb7a07a08f8d65ed Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 052/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 70 ++--- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 17 +- .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProberModule.java | 83 ++++-- .../monitoring/blackbox/ProbingAction.java | 17 +- .../monitoring/blackbox/ProbingSequence.java | 117 +++++---- .../monitoring/blackbox/ProbingStep.java | 177 ++++++------- .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 12 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 ++++ .../monitoring/blackbox/WebWhoisModule.java | 170 ++++++------ .../exceptions/EppClientException.java | 29 ++ .../exceptions/InternalException.java | 29 ++ .../exceptions/ResponseException.java | 29 ++ .../ServerSideException.java | 4 +- .../blackbox/handlers/ActionHandler.java | 88 ++++--- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/WebWhoisActionHandler.java | 19 +- .../handlers/WebWhoisMessageHandler.java | 31 +-- .../blackbox/messages/HttpRequestMessage.java | 50 +--- .../messages/HttpResponseMessage.java | 32 +-- .../messages/OutboundMessageType.java | 11 +- .../blackbox/ProbingActionTest.java | 158 +++++------ .../blackbox/ProbingSequenceStepTest.java | 219 ++++++++++++++++ .../blackbox/TestServers/TestServer.java | 57 ++-- .../blackbox/TestServers/WebWhoisServer.java | 33 +-- .../monitoring/blackbox/TestUtils.java | 144 +++++++++- .../monitoring/blackbox/TokenTest.java | 60 +++++ .../blackbox/handlers/ConversionHandler.java | 11 +- .../blackbox/handlers/NettyRule.java | 62 +---- .../handlers/SslClientInitializerTest.java | 49 +++- .../blackbox/handlers/TestActionHandler.java | 15 +- .../handlers/WebWhoisActionHandlerTest.java | 247 +++++++++++++----- 36 files changed, 1589 insertions(+), 712 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/build.gradle b/prober/build.gradle index 259b093e35e..e48eacb8bf9 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -17,40 +17,42 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { - def deps = rootProject.dependencyMap - - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - - runtime deps['com.google.flogger:flogger-system-backend'] - runtime deps['com.google.auto.value:auto-value'] - runtime deps['io.netty:netty-tcnative-boringssl-static'] - - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') - - // Include auto-value in compile until nebula-lint understands - // annotationProcessor - annotationProcessor deps['com.google.auto.value:auto-value'] - testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] + def deps = rootProject.dependencyMap + + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] + + runtime deps['com.google.flogger:flogger-system-backend'] + runtime deps['com.google.auto.value:auto-value'] + runtime deps['io.netty:netty-tcnative-boringssl-static'] + + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') + //testCompile project(path: ':core', configuration: 'testRuntime') + + // Include auto-value in compile until nebula-lint understands + // annotationProcessor + annotationProcessor deps['com.google.auto.value:auto-value'] + testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 84cf75492f2..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -52,6 +53,7 @@ public Channel channel() { return this.channel; } + @Override public abstract Builder toBuilder(); @@ -83,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -116,9 +118,10 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } + @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -127,4 +130,6 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } + } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 333330207f1..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,16 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index f9db4865f78..73bd9127852 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,68 +14,99 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import io.netty.channel.Channel; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SslProvider; import java.util.Set; import javax.inject.Singleton; -import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores - * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. + * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} + * + *

Provides

*/ @Module public class ProberModule { + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; - /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - - /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides - @Singleton - Class provideChannelClazz() { - return NioSocketChannel.class; + @HttpWhoisProtocol + ProbingSequence provideHttpWhoisSequence( + @HttpWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ + @Provides - @Singleton - Duration provideDuration() { - return DEFAULT_DURATION; + @HttpsWhoisProtocol + ProbingSequence provideHttpsWhoisSequence( + @HttpsWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; + } + + @Provides + @HttpsWhoisProtocol + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } - /** Root level {@link Component} that provides each {@link ProbingSequence}. */ + @Provides + ImmutableMap providePortToProtocolMap( + Set protocolSet) { + return Maps.uniqueIndex(protocolSet, Protocol::port); + } + + + @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, + TokenModule.class }) public interface ProberComponent { - //Standard WebWhois sequence - Set sequences(); + @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); + + @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); + + ImmutableMap providePortToProtocolMap(); + + @WebWhoisProtocol Token provideWebWhoisToken(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2441debb12d..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -34,7 +34,7 @@ import javax.inject.Provider; /** - *Superclass that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -183,4 +183,19 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + @Override + public String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n" + + "path: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host(), + path() + ); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 91c4165c068..6387207fea4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,86 +14,109 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. + * Represents Sequence of {@link ProbingSteps} that the Prober performs in order * + * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} + * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /**Each {@link ProbingSequence} requires a start token to begin running. */ - private Token startToken; + /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ + private EventLoopGroup eventGroup; - public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ + private Bootstrap bootstrap; + + public Bootstrap getBootstrap() { + return bootstrap; + } + + public void start(Token token) { + // calls the first step with input token; + firstStep.accept(token); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * {@link Builder} which takes in {@link ProbingStep}s + * + * @param Same specified {@code C} for overall {@link ProbingSequence} */ - public static class Builder { - - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - - private Token startToken; - - public Builder(Token startToken) { - this.startToken = startToken; + public static class Builder { + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstSequenceStep; + private EventLoopGroup eventLoopGroup; + private Class classType; + + Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; + return this; } - /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, - * built, and pointed to by the previous {@link ProbingStep} added. - */ - public Builder addStep(ProbingStep step) { - - if (currentStep == null) + Builder addStep(ProbingStep step) { + if (currentStep == null) { firstStep = step; - else + } else { currentStep.nextStep(step); - + } currentStep = step; return this; } - /** We take special note of the first repeated step. */ - public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; + /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ + Builder makeFirstRepeated() { + firstSequenceStep = currentStep; + return this; + } + /** Set the class to be the same as {@code C} */ + public Builder setClass(Class classType) { + this.classType = classType; return this; } - /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and - * calls private constructor to create {@link ProbingSequence}. - */ - public ProbingSequence build() { - if (firstRepeatedStep == null) - firstRepeatedStep = firstStep; - - currentStep.nextStep(firstRepeatedStep); + public ProbingSequence build() { + currentStep.nextStep(firstSequenceStep); currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); } + } - private ProbingSequence(ProbingStep firstStep, Token startToken) { + /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ + private void setParents() { + ProbingStep currentStep = firstStep.parent(this).nextStep(); + + while (currentStep != firstStep) { + currentStep = currentStep.parent(this).nextStep(); + } + } + private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, + Class classType) { this.firstStep = firstStep; - this.startToken = startToken; + this.eventGroup = eventLoopGroup; + this.bootstrap = new Bootstrap() + .group(eventGroup) + .channel(classType); + setParents(); + } + + @Override + public String toString() { + return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 3df536a9478..5bad5abf6bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,164 +14,155 @@ package google.registry.monitoring.blackbox; -import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.io.IOException; import java.util.function.Consumer; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step - * in {@link ProbingSequence}. + * Represents generator of actions performed at each step in {@link ProbingSequence} + * + * @param See {@code C} in {@link ProbingSequence} * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. - * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, - * generates a new {@link ProbingAction} to call.

+ * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies + * these components on each loop iteration with the consumed {@link Token} and from that, + * generates new {@link ProbingAction} to perform<./p> * + *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -@AutoValue -public abstract class ProbingStep implements Consumer { +public abstract class ProbingStep implements Consumer { + public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); + protected static final Duration DEFAULT_DURATION = new Duration(2000L); private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Necessary boolean to inform when to obtain next {@link Token}*/ - protected boolean isLastStep = false; - private ProbingStep nextStep; - - /** Time delay duration between actions. */ - abstract Duration duration(); - - /** {@link Protocol} type for this step. */ - abstract Protocol protocol(); - - /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ - abstract OutboundMessageType messageTemplate(); - - /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ - abstract Bootstrap bootstrap(); - + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + protected LocalAddress address = DEFAULT_ADDRESS; - @AutoValue.Builder - public static abstract class Builder { - public abstract Builder setDuration(Duration value); + /** Necessary boolean to inform when to obtain next {@link Token}*/ + private boolean isLastStep = false; + private ProbingStep nextStep; + private ProbingSequence parent; - public abstract Builder setProtocol(Protocol value); + protected Duration duration; - public abstract Builder setMessageTemplate(OutboundMessageType value); + protected final Protocol protocol; + protected final OutboundMessageType message; - public abstract Builder setBootstrap(Bootstrap value); + protected ProbingStep(Protocol protocol, OutboundMessageType message) { + this.protocol = protocol; + this.message = message; + } - public abstract ProbingStep build(); + private OutboundMessageType message() { + return message; } - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); + Protocol protocol() { + return protocol; } + void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { - OutboundMessageType message = token.modifyMessage(messageTemplate()); - ProbingAction.Builder probingActionBuilder = ProbingAction.builder() - .setDelay(duration()) - .setProtocol(protocol()) - .setOutboundMessage(message) - .setHost(token.host()); - - if (token.channel() != null) - probingActionBuilder.setChannel(token.channel()); - else - probingActionBuilder.setBootstrap(bootstrap()); - - return probingActionBuilder.build(); + ProbingStep parent(ProbingSequence parent) { + this.parent = parent; + return this; } + /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + private ProbingAction generateAction(Token token) throws InternalException { + ProbingAction generatedAction; + + OutboundMessageType message = token.modifyMessage(message()); + + //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction + if (protocol().persistentConnection() && token.channel() != null) { + generatedAction = ExistingChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .channel(token.channel()) + .build(); + } else { + generatedAction = NewChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .bootstrap(parent.getBootstrap()) + .address(address) + .build(); + + } + return generatedAction; + } - /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ + + /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

- */ @Override public void accept(Token token) { - ProbingAction currentAction; + ProbingAction nextAction; //attempt to generate new action. On error, move on to next step try { - currentAction = generateAction(token); - } catch(UndeterminedStateException e) { + nextAction = generateAction(token); + } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch(Exception e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; + //If the next step maintains the connection, pass on the channel from this + if (protocol().persistentConnection()) { + token.channel(nextAction.channel()); } + //call the created action + ChannelFuture future = nextAction.call(); + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - + nextStep.accept(generateNextToken(token)); } else { - //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - - if (protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n", + "OutboundMessage: %s\n" + + "and parent sequence: %s", protocol(), - messageTemplate().getClass().getName()); + message(), + parent); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 4b0727229c1..24c666b8d9d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -108,4 +108,16 @@ public abstract static class Builder { public abstract Protocol build(); } + + @Override + public String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index de041afad38..dba905c0e49 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,96 +18,90 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; + +import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; - private static final String HTTP_PROTOCOL_NAME = "http"; - private static final String HTTPS_PROTOCOL_NAME = "https"; - - /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ - private static final int maximumMessageLengthBytes = 512 * 1024; + final static String DOMAIN_SUFFIX = "whois.nic."; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpWhoisProtocol {} + @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpsWhoisProtocol {} + @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - /** {@link Provides} standard WebWhois sequence. */ + + + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + + @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { + @HttpWhoisProtocol + static ProbingStep provideHttpWhoisProbingSequence( + @HttpWhoisProtocol Protocol httpWhoisProtocol) { + return new ProbingStepWeb<>(httpWhoisProtocol); + } - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); + @Provides + @HttpsWhoisProtocol + static ProbingStep provideHttpsWhoisProbingStep( + @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { + return new ProbingStepWeb<>(httpsWhoisProtocol); } - /** {@link Provides} only step used in WebWhois sequence. */ + @Singleton @Provides - @WebWhoisProtocol - static ProbingStep provideWebWhoisStep( - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @WebWhoisProtocol Bootstrap bootstrap, - HttpRequestMessage messageTemplate, - Duration duration) { - - return ProbingStep.builder() - .setProtocol(httpWhoisProtocol) - .setBootstrap(bootstrap) - .setMessageTemplate(messageTemplate) - .setDuration(duration) + @HttpWhoisProtocol + static Protocol provideHttpWhoisProtocol( + @HttpWhoisProtocol int httpWhoisPort, + @HttpWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides - @HttpWhoisProtocol - static Protocol provideHttpWhoisProtocol( + @IntoSet + static Protocol provideHttpProtocolForSet( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTP_PROTOCOL_NAME) - .setPort(httpWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ + @Singleton @Provides @HttpsWhoisProtocol @@ -115,21 +109,40 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTPS_PROTOCOL_NAME) - .setPort(httpsWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } + @Singleton + @Provides + @IntoSet + static Protocol provideHttpsProtocolForSet( + @HttpsWhoisProtocol int httpsWhoisPort, + @HttpsWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Provides + @WebWhoisProtocol + String provideHttpWhoisHost() { + return "app"; + } + - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -138,14 +151,13 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -155,60 +167,34 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } - @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); - } - - @Provides - static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { - return new HttpObjectAggregator(maxContentLength); - } - - /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ - @Provides - @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); - } - /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ - @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap( - EventLoopGroup eventLoopGroup, - Class channelClazz){ - return new Bootstrap() - .group(eventLoopGroup) - .channel(channelClazz); + static MessageHandler provideMessageHandler() { + return new WebWhoisMessageHandler(); } @Provides - @WebWhoisProtocol - int provideMaximumMessageLengthBytes() { - return maximumMessageLengthBytes; + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); } - /** {@link Provides} the list of top level domains to be probed */ - @Singleton @Provides - @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); + static HttpObjectAggregator provideHttpObjectAggregator() { + return new HttpObjectAggregator(1048576); } @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return HTTP_WHOIS_PORT; + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } @Provides @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return HTTPS_WHOIS_PORT; + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 503d211b324..7898203e92d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,68 +15,88 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import com.google.common.flogger.StackSize; -import io.netty.channel.ChannelInboundHandlerAdapter; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpResponse; -import java.util.function.Function; -import javax.inject.Inject; /** + *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - * @param Generic Type of Inbound Message - * @param Generic Type of Outbound Message - * Abstract class that tells sends message down pipeline and - * and tells listeners to move on when the message is received. + *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

+ * + *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} + * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception + * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses + * specify further work to be done for specific kinds of channel pipelines.

*/ -public abstract class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - protected ChannelPromise finished; - private Channel channel; + /** Three types of responses received down pipeline */ + public enum ResponseType {SUCCESS, FAILURE, ERROR} + /** Status of response for current {@link ActionHandler} instance */ + private static ResponseType status; - /** returns ChannelPromise for when inbound message is recieved - * a - * @param outboundMessage - * @return - */ - @Override - public ChannelFuture apply(O outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline + protected ChannelPromise finished; - channel.writeAndFlush(outboundMessage); + /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + public ChannelFuture getFuture() { return finished; - - } - - public void resetFuture() { - finished = channel.newPromise(); } + /** Initializes new {@link ChannelPromise} */ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler - - channel = ctx.channel(); finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ - //Only purpose of Handler is to mark future as a success - + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + //simply marks finished as success + status = ResponseType.SUCCESS; finished.setSuccess(); } + /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); + logger.atSevere().withCause(cause).log(String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), + ctx.channel().pipeline().toString())); + + + if (ResponseException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + status = ResponseType.FAILURE; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (ServerSideException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + status = ResponseType.ERROR; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (InternalException.class.isInstance(cause)){ + logger.atSevere().withCause(cause).log("Severe internal error"); + finished.setFailure(cause); + } else { + finished.setFailure(cause); + } + + //due to failure, close channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 5b77461cd8f..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -17,20 +17,16 @@ import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; @@ -59,7 +55,7 @@ public WebWhoisActionHandler() {} */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ServerSideException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -67,9 +63,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - finished.setSuccess(); - logger.atInfo().log("Response Received: " + response); + super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -79,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -126,10 +121,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + throw new ResponseException("Response received from remote site was: " + response.status()); } } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 58c395ad86e..4afc5d95ba7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,52 +1,33 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -/** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} - * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection. - */ -public class WebWhoisMessageHandler extends ChannelDuplexHandler { +public class WebWhoisMessageHandler extends MessageHandler { + + private HttpRequestMessage request; @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - HttpRequestMessage request = (HttpRequestMessage) msg; + request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + FullHttpResponse originalResponse = (FullHttpResponse) msg; - HttpResponseMessage response = new HttpResponseMessage(originalResponse); + InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8fbb55c6339..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,13 +6,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} - * (but needs to implement {@link OutboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion - * from {@link FullHttpRequest} to its type

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -35,6 +14,11 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + + @Override public HttpRequestMessage setUri(String path) { @@ -42,22 +26,16 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - - //creates message based on content found in original request - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - - - //stores headers from request in finalRequest - request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - - return finalRequest; - + HttpRequestMessage output; + if (buf == null) { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + } else { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + } + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 776e7de0824..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,33 +1,11 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} - * (but needs to implement {@link InboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion - * from {@link FullHttpResponse} to its type

- */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -39,20 +17,22 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } - /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); - //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - //stores headers from response in finalResponse - response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); return finalResponse; } + + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 6e3da3f69d2..0dd17e9d4a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,17 +14,8 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; - /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType { - - /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; +public interface OutboundMessageType {} - /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - @Override - String toString(); -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index f7857dd80f9..cbcf2fc82b0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,19 +15,20 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -38,7 +39,6 @@ import io.netty.channel.nio.NioEventLoopGroup; import javax.inject.Provider; import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,65 +51,99 @@ * */ @RunWith(JUnit4.class) public class ProbingActionTest { - private static final String TEST_MESSAGE = "MESSAGE_TEST"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final int TEST_PORT = 0; - - private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + /** Necessary Constants for test */ + private final String TEST_MESSAGE = "MESSAGE_TEST"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final int TEST_PORT = 0; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = () -> testHandler; - private Provider conversionHandlerProvider = () -> conversionHandler; + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + private ProbingAction newChannelAction; + private ProbingAction existingChannelAction; + private EmbeddedChannel channel; + private Protocol protocol; /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); + /** Sets up a {@link Protocol} corresponding to when a new connection is created */ + private void setupNewChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(false) + .build(); + } + /** Sets up a {@link Protocol} corresponding to when a new connection exists */ + private void setupExistingChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(true) + .build(); + } + + /** Sets up a {@link NewChannelAction} with test specified attributes */ + private void setupNewChannelAction() { + newChannelAction = NewChannelAction.builder() + .bootstrap(bootstrap) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .address(address) + .build(); + } + + private void setupChannel() { + channel = new EmbeddedChannel(); + } + + /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + private void setupExistingChannelAction(Channel channel) { + existingChannelAction = ExistingChannelAction.builder() + .channel(channel) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .build(); + } - @Ignore @Test public void testBehavior_existingChannel() { //setup - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up a Protocol corresponding to when a connection exists. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(true) - .build(); + setupChannel(); + setupExistingChannelProtocol(); + setupExistingChannelAction(channel); + channel.pipeline().addLast(conversionHandler); + channel.pipeline().addLast(testHandler); - // Sets up a ProbingAction that creates a channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setChannel(channel) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost("") - .build(); - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = existingChannelAction.call(); - //Obtains the outboundMessage passed through pipeline after delay - Object msg = null; - while (msg == null) { - msg = channel.readOutbound(); - } - //tests the passed message is exactly what we expect + //Ensures that we pass in the right message to the channel and haven't marked the future as success yet + Object msg = channel.readOutbound(); assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - assertThat(request).isEqualTo(TEST_MESSAGE); - - // Ensures that we haven't marked future as done until response is received. - assertThat(future.isDone()).isFalse(); + String response = ((ByteBuf) msg).toString(UTF_8); + assertThat(response).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()).isFalse(); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); @@ -121,41 +155,19 @@ public void testBehavior_existingChannel() { @Test public void testSuccess_newChannel() throws Exception { //setup - - LocalAddress address = new LocalAddress(ADDRESS_NAME); - Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); - - // Sets up a Protocol corresponding to when a new connection is created. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - + setupNewChannelProtocol(); + setupNewChannelAction(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - // Sets up a ProbingAction with existing channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.syncUninterruptibly(); + future.sync(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()); + assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java new file mode 100644 index 00000000000..7a713017072 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java @@ -0,0 +1,219 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.TestUtils.TestStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.handlers.ConversionHandler; +import google.registry.monitoring.blackbox.handlers.NettyRule; +import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.junit.Rule; +import org.junit.Test; + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + + /** Used for testing how well probing step can create connection to blackbox server */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + + + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ + private ProbingSequence testSequence; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); + dummyStep = new DummyStep(testProtocol, eventLoopGroup); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(false) + .build(); + } + + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(true) + .build(); + } + + /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ + private void setupSequence() { + testSequence = new ProbingSequence.Builder() + .eventLoopGroup(eventLoopGroup) + .setClass(LocalChannel.class) + .addStep(firstStep) + .makeFirstRepeated() + .addStep(dummyStep) + .build(); + } + + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //there should be no next step + assertThat(firstStep.nextStep()).isNull(); + + //we expect that this exception be thrown + assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); + + } + + @Test + public void testWithSequence_NewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupSequence(); + setupNewChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupSequence(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 46615a506fb..67e2cb7165d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,40 +1,37 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform */ public abstract class TestServer { + private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + this.localAddress = localAddress; + //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override @@ -54,5 +51,35 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** Saves any inbound error as the cause of the promise failure. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 4da75b31c25..ab9997b6c68 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -19,13 +5,11 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -36,10 +20,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - *

It will either redirect the client to the correct location if given the + * It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location

+ * an unexpected host location */ public class WebWhoisServer extends TestServer { @@ -75,14 +59,14 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { + static class RedirectHandler extends ChannelDuplexHandler { private String redirectInput; private String destinationInput; /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; @@ -91,14 +75,15 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { + public void channelRead(ChannelHandlerContext ctx, Object msg) { + HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 50c60d9fc52..8d1722c9625 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,24 +14,47 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { + static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -56,19 +79,102 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain"); + response.headers().set("content-type", "text/plain").set("content-length", "0"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; + } + + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); return response; } + /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ + public static class TestProvider implements Provider { + + private E obj; + + public TestProvider(E obj) { + this.obj = obj; + } + + @Override + public E get() { + return obj; + } + } + + /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ + public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { + + String message; + + public DuplexMessageTest() { + message = ""; + } + + public DuplexMessageTest(String msg) { + message = msg; + } + + @Override + public String toString() { + return message; + } + } + + /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ + public static class TestStep extends ProbingStep { + + public TestStep(Protocol protocol, String testMessage, LocalAddress address) { + super(protocol, new DuplexMessageTest(testMessage)); + this.address = address; + this.duration = Duration.ZERO; + } + } + + /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ + public static class DummyStep extends ProbingStep { + private DefaultPromise future; + + public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { + super(protocol, new DuplexMessageTest()); + future = new DefaultPromise(eventLoopGroup.next()) {}; + duration = Duration.ZERO; + } + + @Override + public void accept(Token token) { + future.setSuccess(token); + } + public DefaultPromise getFuture() { + return future; + } + } + /** Basic outline for {@link Token} instances to be used in tests */ - static abstract class TestToken extends Token { - protected String host; + private static abstract class TestToken extends Token { + private String host; protected TestToken(String host) { this.host = host; @@ -84,7 +190,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String host() { + public String getHost() { return host; } @@ -114,5 +220,33 @@ public Channel channel() { return channel; } } + + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java new file mode 100644 index 00000000000..ef5cba5b60d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -0,0 +1,60 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + */ +@RunWith(JUnit4.class) +public class TokenTest { + + private static String PREFIX = "whois.nic."; + private static String TEST_STARTER = "starter"; + private static String TEST_DOMAIN = "test"; + + public Token webToken = new WebWhoisToken(TEST_DOMAIN); + + @Test + public void testWebToken_MessageModificationSuccess() { + //creates Request message with header + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + message.headers().set("host", TEST_STARTER); + + //attempts to use Token's method for modifying the method based on its stored host + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { + throw new RuntimeException(e); + } + + + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index c9d337d6ad8..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,13 +17,10 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -31,8 +28,8 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 86b54d9a07d..b6b5e8fbe0c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -25,11 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingActionTest; -import google.registry.monitoring.blackbox.ProbingStepTest; -import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -41,6 +41,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -51,8 +52,8 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

+ *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -79,19 +80,16 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { + public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, - ImmutableList.builder().add(handlers).add(echoHandler).build()); + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); } /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - Protocol protocol, - String host, + ProbingAction probingAction, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -111,9 +109,7 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol) - .attr(REMOTE_ADDRESS_KEY, host); - + .attr(PROBING_ACTION_KEY, probingAction); channel = b.connect(localAddress).syncUninterruptibly().channel(); } @@ -122,7 +118,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertReceivedMessage(String message) throws Exception { + public void assertThatCustomWorks(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -163,38 +159,6 @@ ThrowableSubject assertThatClientRootCause() { } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** - * Saves any inbound error as the cause of the promise failure. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 523fb228752..469c62a8f75 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,14 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.ExistingChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; @@ -41,6 +45,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; +import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -62,6 +67,8 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { + private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); + /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -86,12 +93,15 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private final static Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .persistentConnection(false) + .build(); + + private ProbingAction probingAction; private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -103,13 +113,23 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } + private void setupProbingAction(Channel channel) { + probingAction = ExistingChannelAction.builder() + .delay(Duration.ZERO) + .host(SSL_HOST) + .channel(channel) + .outboundMessage(DEFAULT_MESSAGE) + .protocol(PROTOCOL) + .build(); + } + @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - channel.attr(PROTOCOL_KEY).set(PROTOCOL); - channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); + setupProbingAction(channel); + channel.attr(PROBING_ACTION_KEY).set(probingAction); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -140,7 +160,8 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -168,7 +189,8 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -197,7 +219,8 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 95b06e623d1..518bb9ba686 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,7 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -23,18 +22,18 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ - private InboundMessageType receivedMessage; + private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage; + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } - public InboundMessageType getResponse() { + @Override + public String toString() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 63bb2cf5b53..d8a672758da 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,32 +15,44 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; +import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ +/** + * Unit tests for {@link WebWhoisActionHandler}. + * + *

Attempts to test how well {@link WebWhoisActionHandler} works + * when responding to all possible types of responses

+ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; @@ -50,89 +62,96 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; + private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); + private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - + private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; + private ProbingAction probingAction; + private Provider actionHandlerProvider; + private void generateLocalAddress() { + address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + } /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { + private Protocol createProtocol(String name, int port) { return Protocol.builder() .name(name) .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); + .handlerProviders(ImmutableList.of(actionHandlerProvider)) + .persistentConnection(false) + .build(); } /** Initializes new WebWhoisActionHandler */ private void setupActionHandler() { actionHandler = new WebWhoisActionHandler(); + actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); + private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + setupProbingActionBasic( + protocol, + outboundMessage, + makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); + channel.attr(PROBING_ACTION_KEY).set(probingAction); } + private Bootstrap makeBootstrap(EventLoopGroup group) { + return new Bootstrap() + .group(group) + .channel(LocalChannel.class); + } /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() + private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + probingAction = NewChannelAction.builder() .protocol(protocol) .outboundMessage(outboundMessage) .delay(DEFAULT_DURATION) .bootstrap(bootstrap) + .host(TARGET_HOST) + .address(DEFAULT_ADDRESS) .build(); } - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); + private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(host) + .address(address) + .build(); } - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; + private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testSuccess_responseOk() { + public void testBasic_responseOk() throws Exception { //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -140,25 +159,30 @@ public void testSuccess_responseOk() { channel.writeInbound(response); - //assesses that we successfully receivved good response and protocol is unchanged + //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testSuccess_responseBad() { + public void testBasic_responseFailure() { //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseBad", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + FullHttpResponse response = HttpResponseMessage + .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -167,24 +191,63 @@ public void testSuccess_responseBad() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + } + @Test + public void testBasic_responseError() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseError", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + + //stores future + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, and event is success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testSuccess_redirectCloseChannel() { + public void testBasic_redirectCloseChannel() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); + HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", 0); + generateLocalAddress(); + setupChannel(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(outboundMessage); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + //checks that future has not been set to successful or a failure + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); @@ -195,27 +258,69 @@ public void testSuccess_redirectCloseChannel() { } @Test - public void testSuccess_redirectHost() { + public void testBasic_redirectHost() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); channel.writeInbound(originalResponse); + ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); + Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); + assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); + } + + @Test + public void testAdvanced_responseOk() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", TARGET_HOST, group); + //stores future + ChannelFuture future = probingAction.call(); + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + } + + @Test + public void testAdvanced_responseFailure() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", TARGET_HOST, group); + + //stores future + ChannelFuture future = probingAction.call(); + + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } } + From 4a287c45b7e0dfc51dd16d174d1cf8cf6ab19bcc Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 053/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 +++++++++----- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/ProbingSequence.java | 1 - .../monitoring/blackbox/ProbingStep.java | 7 +--- .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 - .../monitoring/blackbox/Tokens/Token.java | 4 +- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../monitoring/blackbox/WebWhoisModule.java | 2 +- .../exceptions/EppClientException.java | 29 ------------- .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++- .../handlers/WebWhoisMessageHandler.java | 22 +++++++++- .../blackbox/messages/HttpRequestMessage.java | 41 +++++++++++++------ .../messages/HttpResponseMessage.java | 26 ++++++++---- .../messages/OutboundMessageType.java | 1 - .../blackbox/TestServers/TestServer.java | 16 +++++++- .../blackbox/TestServers/WebWhoisServer.java | 18 +++++++- 19 files changed, 145 insertions(+), 85 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6387207fea4..2eb90a1d6c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -119,4 +119,3 @@ public String toString() { } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 5bad5abf6bf..80b04a3d0c9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.exceptions.EppClientException; import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; import io.netty.channel.local.LocalAddress; -import java.io.IOException; + import java.util.function.Consumer; import org.joda.time.Duration; @@ -164,7 +162,4 @@ public String toString() { message(), parent); } - } - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 24c666b8d9d..61c83de00fd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -120,4 +120,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dba905c0e49..7200a1877e2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -197,4 +197,4 @@ static SslClientInitializer provideSslClientInitializer(SslPro } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 4afc5d95ba7..0acf223eb9e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; @@ -8,6 +22,11 @@ import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; +/** + * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} + * in case of reuse for redirection + */ public class WebWhoisMessageHandler extends MessageHandler { private HttpRequestMessage request; @@ -15,6 +34,7 @@ public class WebWhoisMessageHandler extends MessageHandler { @Inject public WebWhoisMessageHandler() {} + /** Retains {@link HttpRequestMessage} and calls super write method*/ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { request = (HttpRequestMessage) msg; @@ -23,9 +43,9 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) } + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - FullHttpResponse originalResponse = (FullHttpResponse) msg; InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..b06938d80a1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +31,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,16 +38,19 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + + request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + + return finalRequest; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..283b14440ac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,7 +33,7 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); @@ -26,13 +43,8 @@ public static HttpResponseMessage fromResponse(FullHttpResponse response) { else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); return finalResponse; } - - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 0dd17e9d4a9..2d5df10f8c1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType {} - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 67e2cb7165d..a4474b6b8b5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static com.google.common.truth.Truth.assertThat; @@ -20,7 +34,7 @@ import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { private LocalAddress localAddress; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index ab9997b6c68..06b19ea3607 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -20,10 +34,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - * It will either redirect the client to the correct location if given the + *

It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location + * an unexpected host location

*/ public class WebWhoisServer extends TestServer { From 89b268084c226b5f9820fad31305dfe2318bcc54 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 054/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 --- .../monitoring/blackbox/NewChannelAction.java | 144 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProberModule.java | 80 ++--- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingSequence.java | 130 ++++----- .../monitoring/blackbox/ProbingStep.java | 147 +++++----- .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/Protocol.java | 78 +---- .../monitoring/blackbox/TokenModule.java | 35 --- .../monitoring/blackbox/Tokens/Token.java | 47 --- .../blackbox/Tokens/WebWhoisToken.java | 54 ---- .../monitoring/blackbox/WebWhoisModule.java | 169 ++++++----- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/ActionHandler.java | 102 +++++-- .../blackbox/handlers/MessageHandler.java | 24 -- .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../handlers/WebWhoisMessageHandler.java | 17 +- .../blackbox/messages/HttpRequestMessage.java | 46 ++- .../messages/HttpResponseMessage.java | 14 +- .../messages/OutboundMessageType.java | 11 +- .../monitoring/blackbox/tokens/Token.java | 20 +- .../blackbox/tokens/WebWhoisToken.java | 32 +- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 32 files changed, 704 insertions(+), 987 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 73bd9127852..0daaf16ded4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,99 +14,59 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; import javax.inject.Singleton; +import org.joda.time.Duration; /** - * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} - * - *

Provides

+ * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores + * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. */ @Module public class ProberModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; + /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + private static final Duration DEFAULT_DURATION = new Duration(4000L); + + /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides - @HttpWhoisProtocol - ProbingSequence provideHttpWhoisSequence( - @HttpWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpsWhoisProtocol - ProbingSequence provideHttpsWhoisSequence( - @HttpsWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return httpWhoIsPort; - } - - @Provides - @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return httpsWhoIsPort; + @Singleton + Duration provideDuration() { + return DEFAULT_DURATION; } + /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - ImmutableMap providePortToProtocolMap( - Set protocolSet) { - return Maps.uniqueIndex(protocolSet, Protocol::port); + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - - + /** Root level {@link Component} that provides each {@link ProbingSequence}. */ @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, - TokenModule.class }) public interface ProberComponent { - @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); - - @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); - - ImmutableMap providePortToProtocolMap(); - - @WebWhoisProtocol Token provideWebWhoisToken(); + //Standard WebWhois sequence + @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2eb90a1d6c3..2dbf48256f9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,108 +14,100 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} - * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ - private EventLoopGroup eventGroup; + /**Each {@link ProbingSequence} requires a start token to begin running. */ + private Token startToken; - /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ - private Bootstrap bootstrap; - - public Bootstrap getBootstrap() { - return bootstrap; - } - - public void start(Token token) { - // calls the first step with input token; - firstStep.accept(token); + public void start() { + // calls the first step with startToken; + firstStep.accept(startToken); } /** - * {@link Builder} which takes in {@link ProbingStep}s - * - * @param Same specified {@code C} for overall {@link ProbingSequence} + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. */ - public static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstSequenceStep; - private EventLoopGroup eventLoopGroup; - private Class classType; - - Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public static class Builder { + + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstRepeatedStep; + private Bootstrap bootstrap; + private Token startToken; + + /** + * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. + * + *

Must be called before adding {@link ProbingStep.Builder}s.

+ */ + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } + + /** Adds start token that activate {@link ProbingSequence}. */ + public Builder addToken(Token token) { + startToken = token; return this; } - Builder addStep(ProbingStep step) { - if (currentStep == null) { + /** + * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * built, and pointed to by the previous {@link ProbingStep} added. + */ + public Builder addStep(ProbingStep.Builder stepBuilder) { + assert (bootstrap != null); + ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + + if (currentStep == null) firstStep = step; - } else { + else currentStep.nextStep(step); - } + currentStep = step; return this; } - /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ - Builder makeFirstRepeated() { - firstSequenceStep = currentStep; - return this; - } - /** Set the class to be the same as {@code C} */ - public Builder setClass(Class classType) { - this.classType = classType; + /** We take special note of the first repeated step. */ + public Builder markFirstRepeated() { + firstRepeatedStep = currentStep; return this; } - public ProbingSequence build() { - currentStep.nextStep(firstSequenceStep); + /** + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and + * calls private constructor to create {@link ProbingSequence}. + */ + public ProbingSequence build() { + if (firstRepeatedStep == null) + firstRepeatedStep = firstStep; + + currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); - return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + return new ProbingSequence(this.firstStep, this.startToken); } - } - /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ - private void setParents() { - ProbingStep currentStep = firstStep.parent(this).nextStep(); - - while (currentStep != firstStep) { - currentStep = currentStep.parent(this).nextStep(); - } - } - private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, - Class classType) { + private ProbingSequence(ProbingStep firstStep, Token startToken) { this.firstStep = firstStep; - this.eventGroup = eventLoopGroup; - this.bootstrap = new Bootstrap() - .group(eventGroup) - .channel(classType); - setParents(); - } - - @Override - public String toString() { - return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); - + this.startToken = startToken; } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 80b04a3d0c9..d54acef325a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,152 +14,145 @@ package google.registry.monitoring.blackbox; +import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.local.LocalAddress; - import java.util.function.Consumer; import org.joda.time.Duration; /** - * Represents generator of actions performed at each step in {@link ProbingSequence} - * - * @param See {@code C} in {@link ProbingSequence} + * {@link AutoValue} class that represents generator of actions performed at each step + * in {@link ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies - * these components on each loop iteration with the consumed {@link Token} and from that, - * generates new {@link ProbingAction} to perform<./p> + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. + * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, + * generates a new {@link ProbingAction} to call.

* - *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -public abstract class ProbingStep implements Consumer { +@AutoValue +public abstract class ProbingStep implements Consumer { - public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); - protected static final Duration DEFAULT_DURATION = new Duration(2000L); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - protected LocalAddress address = DEFAULT_ADDRESS; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ private boolean isLastStep = false; - private ProbingStep nextStep; - private ProbingSequence parent; + private ProbingStep nextStep; - protected Duration duration; + abstract Duration duration(); + abstract Protocol protocol(); + abstract OutboundMessageType messageTemplate(); + abstract Bootstrap bootstrap(); - protected final Protocol protocol; - protected final OutboundMessageType message; - protected ProbingStep(Protocol protocol, OutboundMessageType message) { - this.protocol = protocol; - this.message = message; - } + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder setDuration(Duration value); - private OutboundMessageType message() { - return message; - } + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); - Protocol protocol() { - return protocol; + public abstract ProbingStep build(); } + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - ProbingStep parent(ProbingSequence parent) { - this.parent = parent; - return this; - } - - /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ private ProbingAction generateAction(Token token) throws InternalException { - ProbingAction generatedAction; - - OutboundMessageType message = token.modifyMessage(message()); - - //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction - if (protocol().persistentConnection() && token.channel() != null) { - generatedAction = ExistingChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .channel(token.channel()) - .build(); - } else { - generatedAction = NewChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .bootstrap(parent.getBootstrap()) - .address(address) - .build(); - - } - return generatedAction; + OutboundMessageType message = token.modifyMessage(messageTemplate()); + ProbingAction.Builder probingActionBuilder = ProbingAction.builder() + .setDelay(duration()) + .setProtocol(protocol()) + .setOutboundMessage(message) + .setHost(token.getHost()) + .setBootstrap(bootstrap()); + + if (token.channel() != null) + probingActionBuilder.setChannel(token.channel()); + + return probingActionBuilder.build(); } - /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } @Override public void accept(Token token) { - ProbingAction nextAction; + ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - nextAction = generateAction(token); + currentAction = generateAction(token); } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - //If the next step maintains the connection, pass on the channel from this - if (protocol().persistentConnection()) { - token.channel(nextAction.channel()); - } + //call the created action - ChannelFuture future = nextAction.call(); + ChannelFuture future; + + try { + future = currentAction.call(); + + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Performed"); + nextStep.accept(generateNextToken(token)); + return; + } + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - nextStep.accept(generateNextToken(token)); + //If the next step maintains the connection, pass on the channel from this } else { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + token.setChannel(currentAction.channel()); + + nextStep.accept(generateNextToken(token)); + + }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n" + - "and parent sequence: %s", + "OutboundMessage: %s\n", protocol(), - message(), - parent); + messageTemplate().getClass().getName()); } + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 61c83de00fd..b0342c74b7d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,95 +16,43 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; +import io.netty.util.AttributeKey; import javax.inject.Provider; /** - * Protocol Class packages all static variables necessary for a certain type of connection - * Both the host and the path can be changed for the same protocol - * Mainly packages the handlers necessary for the requisite channel pipeline + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. */ @AutoValue public abstract class Protocol { - public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - - /** - * Default names associated with each protocol - */ - final static String EPP_PROTOCOL_NAME = "EPP"; - final static String DNS_PROTOCOL_NAME = "DNS"; - final static String WHOIS_PROTOCOL_NAME = "WHOIS"; - final static String RDAP_PROTOCOL_NAME = "RDAP"; - - private String host; - private String path = ""; - private ProbingAction probingAction; - - /** Setter method for Protocol's host*/ - public Protocol host(String host) { - this.host = host; - return this; - } - - /** Getter method for Protocol's host*/ - public String host() { - return host; - } - - /** Setter method for Protocol's path*/ - public Protocol path(String path) { - this.path = path; - return this; - } - - /** Getter method for Protocol's path*/ - public String path() { - return path; - } - - /** Setter method for Protocol's ProbingAction parent*/ - public Protocol probingAction(ProbingAction probingAction) { - this.probingAction = probingAction; - return this; - } - - /** Getter method for Protocol's path*/ - public ProbingAction probingAction() { - return probingAction; - } - - /** If connection associated with Protocol is persistent, which is only EPP */ - public boolean persistentConnection() { - return name() == EPP_PROTOCOL_NAME; - } + /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - /** Protocol Name */ - public abstract String name(); + abstract String name(); - /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - public abstract ImmutableList> handlerProviders(); + abstract ImmutableList> handlerProviders(); - - public abstract Builder toBuilder(); + /** Boolean that notes if connection associated with Protocol is persistent.*/ + abstract boolean persistentConnection(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } - /** Builder for {@link Protocol}. */ @AutoValue.Builder public abstract static class Builder { - public abstract Builder name(String value); + public abstract Builder setName(String value); + + public abstract Builder setPort(int num); - public abstract Builder port(int num); + public abstract Builder setHandlerProviders(ImmutableList> providers); - public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder setPersistentConnection(boolean value); public abstract Protocol build(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 7200a1877e2..dcc9635beaa 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,62 +17,86 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; -import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandler; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - final static String DOMAIN_SUFFIX = "whois.nic."; + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + private static final String DOMAIN_PREFIX = "whois.nic."; + + /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + private static final int maximumMessageLengthBytes = 512 * 1024; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - - - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - - + /** {@link Provides} standard WebWhois sequence. */ @Provides - @HttpWhoisProtocol - static ProbingStep provideHttpWhoisProbingSequence( - @HttpWhoisProtocol Protocol httpWhoisProtocol) { - return new ProbingStepWeb<>(httpWhoisProtocol); + @WebWhoisProtocol + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, + WebWhoisToken webWhoisToken, + @WebWhoisProtocol Bootstrap bootstrap) { + + return new ProbingSequence.Builder() + .addToken(webWhoisToken) + .setBootstrap(bootstrap) + .addStep(probingStepBuilder) + .build(); } + + /** {@link Provides} only step used in WebWhois sequence. */ @Provides - @HttpsWhoisProtocol - static ProbingStep provideHttpsWhoisProbingStep( - @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { - return new ProbingStepWeb<>(httpsWhoisProtocol); + @WebWhoisProtocol + static ProbingStep.Builder provideWebWhoisStepBuilder( + @HttpWhoisProtocol Protocol httpWhoisProtocol, + HttpRequestMessage messageTemplate, + Duration duration) { + + return ProbingStep.builder() + .setProtocol(httpWhoisProtocol) + .setMessageTemplate(messageTemplate) + .setDuration(duration); } - + /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides @HttpWhoisProtocol @@ -80,28 +104,14 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpProtocolForSet( - @HttpWhoisProtocol int httpWhoisPort, - @HttpWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTP_PROTOCOL_NAME) + .setPort(httpWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } - + /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ @Singleton @Provides @HttpsWhoisProtocol @@ -109,40 +119,28 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpsProtocolForSet( - @HttpsWhoisProtocol int httpsWhoisPort, - @HttpsWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTPS_PROTOCOL_NAME) + .setPort(httpsWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } + /** {@link Provides} the prefix where we probe: "prefix.tld". */ @Provides - @WebWhoisProtocol - String provideHttpWhoisHost() { - return "app"; + @Named("Web-WHOIS-Prefix") + String provideWhoisPrefix() { + return DOMAIN_PREFIX; } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -151,13 +149,14 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -167,33 +166,57 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } + @Provides + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); + } + + @Provides + static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { + return new HttpObjectAggregator(maxContentLength); + } + + /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + @Provides + @HttpsWhoisProtocol + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); + } + /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + @Singleton @Provides @WebWhoisProtocol - static MessageHandler provideMessageHandler() { - return new WebWhoisMessageHandler(); + static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + return new Bootstrap() + .group(eventLoopGroup) + .channel(NioSocketChannel.class); } @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); + @WebWhoisProtocol + int provideMaximumMessageLengthBytes() { + return maximumMessageLengthBytes; } + /** {@link Provides} the list of top level domains to be probed */ + @Singleton @Provides - static HttpObjectAggregator provideHttpObjectAggregator() { - return new HttpObjectAggregator(1048576); + @WebWhoisProtocol + ImmutableList provideTopLevelDomains() { + return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); } @Provides - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index adb833ec629..be3d725c833 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,10 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when - * the action performed failed due to an issue in the connection with the server. + * Base exception class for all instances when the status of the action performed is ERROR. */ -public class ConnectionException extends UndeterminedStateException { +public class ConnectionException extends Exception { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 7898203e92d..e397393b4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,10 +14,11 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; @@ -26,16 +27,18 @@ import io.netty.channel.ChannelPromise; /** - *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} - * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception - * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses - * specify further work to be done for specific kinds of channel pipelines.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed + * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} + * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * + *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -47,28 +50,42 @@ public enum ResponseType {SUCCESS, FAILURE, ERROR} /** Status of response for current {@link ActionHandler} instance */ private static ResponseType status; + /** {@link ChannelPromise} that informs {@link google.registry.monitoring.blackbox.ProbingAction} if response has been received. */ protected ChannelPromise finished; - /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** Returns initialized {@link ChannelPromise} to {@link google.registry.monitoring.blackbox.ProbingAction}.*/ public ChannelFuture getFuture() { return finished; } - /** Initializes new {@link ChannelPromise} */ + /** Initializes the same {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } + /** Initializes the same {@link ChannelPromise} in case current channel is reused (usually for EPP).*/ + public void resetFuture() { + finished = finished.channel().newPromise(); + } + + /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { - //simply marks finished as success + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { + status = ResponseType.SUCCESS; - finished.setSuccess(); + + if (!finished.isSuccess()) { + finished.setSuccess(); + } } - /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ + /** + * Logs the channel and pipeline that caused error, closes channel, then informs + * {@link google.registry.monitoring.blackbox.ProbingAction} listeners of error. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).log(String.format( @@ -76,27 +93,62 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.channel().toString(), ctx.channel().pipeline().toString())); - - if (ResponseException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + if (cause instanceof ResponseException) { + //On ResponseException, we know the response is a failure. As a result, + //we set the status to FAILURE, then inform the MetricsHandler of this status = ResponseType.FAILURE; + + //Since it wasn't a success, we still want to log to see what caused the FAILURE logger.atInfo().log(cause.getMessage()); + + //As always, inform the ProbingStep that we successfully completed this action finished.setSuccess(); - } else if (ServerSideException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + + } else if (cause instanceof ConnectionException) { + //On ConnectionException, we know the response type is an error. As a result, + //we set the status to ERROR, then inform the MetricsHandler of this status = ResponseType.ERROR; + + //Since it wasn't a success, we still log what caused the ERROR logger.atInfo().log(cause.getMessage()); finished.setSuccess(); - } else if (InternalException.class.isInstance(cause)){ + + //As this was an ERROR in the connection, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + } else if (cause instanceof InternalException){ + //For an internal error, metrics should not be collected, so we log what caused this, and + //inform the ProbingStep the Prober had an internal error on this action logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); + + + //As this was an internal error, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } else { - finished.setFailure(cause); + //In the case of any other kind of error, we assume it is some type of connection ERROR, + //so we treat it as such: + + status = ResponseType.ERROR; + + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - //due to failure, close channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + + } + + /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ + @VisibleForTesting + ResponseType getStatus() { + return status; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index ac844ac99df..919006592ea 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -89,8 +90,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); - Protocol protocol = action.protocol(); + Protocol protocol = channel.attr(PROTOCOL_KEY).get(); + String host = channel.attr(REMOTE_ADDRESS_KEY).get(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -103,7 +104,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), action.host(), protocol.port()); + .newHandler(channel.alloc(), host, protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 0acf223eb9e..58c395ad86e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -17,37 +17,36 @@ import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; /** - * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection + * in case of reuse for redirection. */ -public class WebWhoisMessageHandler extends MessageHandler { - - private HttpRequestMessage request; +public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method*/ + /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - request = (HttpRequestMessage) msg; + HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; - InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); + HttpResponseMessage response = new HttpResponseMessage(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b06938d80a1..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,19 +19,30 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); @@ -39,18 +50,29 @@ public HttpRequestMessage setUri(String path) { } /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; - ByteBuf buf = request.content(); + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; - request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + } else { + throw new IllegalArgumentException(); + } + } - return finalRequest; + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 283b14440ac..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -34,17 +34,9 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 2d5df10f8c1..be6c872cc3e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,16 @@ package google.registry.monitoring.blackbox.messages; +import google.registry.monitoring.blackbox.exceptions.InternalException; + /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType {} +public interface OutboundMessageType { + + /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + public OutboundMessageType modifyMessage(String... args) throws InternalException; + + /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + public String name(); +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dab5851e8d8..dd1882b5686 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,18 +14,16 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.ProbingSequence; -import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} - * in a single loop of a {@link ProbingSequence}. + * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} + * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes + * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -33,21 +31,17 @@ */ public abstract class Token { - /** - * {@link Channel} that always starts out as null. Once a persistent connection - * is made (such as EPP), that channel is stored in the token and passed on to - * later steps in the sequence until a new loop begins. - */ + /** {@link Channel} that always starts out as null. */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String host(); + public abstract String getHost(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index bb06ee89db6..2847e5ce0eb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; -import java.util.LinkedList; +import java.util.List; import javax.inject.Inject; import javax.inject.Named; @@ -33,38 +33,42 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final static String PREFIX = "whois.nic."; + private final String prefix; /** {@link ImmutableList} of all top level domains to be probed. */ - private final Iterator topLevelDomainsIterator; + private final ImmutableList topLevelDomains; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private String currentDomain; + private int domainsIndex; @Inject - public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken( + @Named("Web-WHOIS-Prefix") String prefix, + @WebWhoisProtocol ImmutableList topLevelDomains) { - topLevelDomainsIterator = topLevelDomains.iterator(); - currentDomain = topLevelDomainsIterator.next(); + domainsIndex = 0; + this.prefix = prefix; + this.topLevelDomains = topLevelDomains; } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + domainsIndex += 1; + domainsIndex %= topLevelDomains.size(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { - return original.modifyMessage(host()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { + return original.modifyMessage(getHost()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String host() { - return PREFIX + currentDomain; + public String getHost() { + return prefix + topLevelDomains.get(domainsIndex); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Mon, 29 Jul 2019 12:04:58 -0400 Subject: [PATCH 055/337] Minor Style Fixes --- .../monitoring/blackbox/ProbingAction.java | 85 ++++++++++--------- .../monitoring/blackbox/ProbingStep.java | 8 +- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..3f6a962b12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -89,11 +90,47 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** The {@link SocketAddress} instance that specifies remote address of connection */ + @Nullable public abstract SocketAddress address(); /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ public abstract Optional bootstrap(); + + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> actionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** * The method that performs the work of the actual action. * @@ -130,41 +167,13 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } @@ -224,7 +233,7 @@ public abstract static class Builder { abstract Channel channel(); - abstract Optional address(); + abstract SocketAddress address(); abstract Optional bootstrap(); @@ -233,7 +242,7 @@ public abstract static class Builder { abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) + if (address() == null) //If no address has been supplied, we set it based on the host and port setAddress(new InetSocketAddress(host(), protocol().port())); @@ -259,7 +268,7 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap().get().connect(address()); setChannel(connectionFuture.channel()); setConnectionFuture(connectionFuture); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index d54acef325a..47c89c72c11 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -21,7 +21,9 @@ import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import java.net.SocketAddress; import java.util.function.Consumer; +import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -48,6 +50,7 @@ public abstract class ProbingStep implements Consumer { abstract Protocol protocol(); abstract OutboundMessageType messageTemplate(); abstract Bootstrap bootstrap(); + @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -60,6 +63,8 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); + public abstract Builder setAddress(SocketAddress address); + public abstract ProbingStep build(); } @@ -87,7 +92,8 @@ private ProbingAction generateAction(Token token) throws InternalException { .setProtocol(protocol()) .setOutboundMessage(message) .setHost(token.getHost()) - .setBootstrap(bootstrap()); + .setBootstrap(bootstrap()) + .setAddress(address()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); From 8daf521f8fa28cac0f9de326cc032dbf790629e9 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:05:59 -0400 Subject: [PATCH 056/337] Updated build.gradle file --- prober/build.gradle | 3 - .../blackbox/ProbingSequenceStepTest.java | 219 ------------------ .../blackbox/ProbingSequenceTest.java | 96 -------- .../monitoring/blackbox/ProbingStepTest.java | 196 ++++++++-------- 4 files changed, 102 insertions(+), 412 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java diff --git a/prober/build.gradle b/prober/build.gradle index e48eacb8bf9..26d44c0a465 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,8 +16,6 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - - dependencies { def deps = rootProject.dependencyMap @@ -46,7 +44,6 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java deleted file mode 100644 index 7a713017072..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.TestUtils.TestStep; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.handlers.ConversionHandler; -import google.registry.monitoring.blackbox.handlers.NettyRule; -import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; -import org.junit.Rule; -import org.junit.Test; - -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { - - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ - private ProbingSequence testSequence; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); - dummyStep = new DummyStep(testProtocol, eventLoopGroup); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(false) - .build(); - } - - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(true) - .build(); - } - - /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ - private void setupSequence() { - testSequence = new ProbingSequence.Builder() - .eventLoopGroup(eventLoopGroup) - .setClass(LocalChannel.class) - .addStep(firstStep) - .makeFirstRepeated() - .addStep(dummyStep) - .build(); - } - - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.nextStep()).isNull(); - - //we expect that this exception be thrown - assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); - - } - - @Test - public void testWithSequence_NewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupSequence(); - setupNewChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupSequence(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 5c4452df7b3..2b0559514a2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,101 +1,5 @@ -// Copyright 2019 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.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doCallRealMethod; - -import google.registry.monitoring.blackbox.tokens.Token; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) public class ProbingSequenceTest { - - private ProbingStep setupMock() { - ProbingStep mock = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(mock).nextStep(); - return mock; - } - - private static class Wrapper { - - T data; - - public Wrapper(T data) { - this.data = data; - } - } - - @Test - public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(firstStep) - .addStep(secondStep) - .addStep(thirdStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(thirdStep); - assertThat(thirdStep.nextStep()).isEqualTo(firstStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - - @Test - public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(thirdStep) - .addStep(secondStep) - .markFirstRepeated() - .addStep(firstStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(firstStep); - assertThat(thirdStep.nextStep()).isEqualTo(secondStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 1f09dd13553..090753014e4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,59 +11,57 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.TestUtils.dummyStep; +import static google.registry.monitoring.blackbox.TestUtils.testStep; +import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; -import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; -import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingStepTest { +public class ProbingSequenceStepTest { /** Basic Constants necessary for tests */ - private final static String ADDRESS_NAME = "TEST_ADDRESS"; - private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final static int PROTOCOL_PORT = 0; - private final static String TEST_MESSAGE = "TEST_MESSAGE"; - private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -74,106 +72,117 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** - * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} - * is called, it just marks the supplied future as succeeded, returning the requisite token. - */ - private ProbingStep dummyStep() { - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(dummyStep).nextStep(); - return dummyStep; + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); } + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } - @Test - public void testNewChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); + dummyStep = dummyStep(eventLoopGroup); - // Sets up Protocol for when we create a new channel. - Protocol testProtocol = Protocol.builder() + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); + } - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) .build(); + } - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); + //there should be no next step + assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); - //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(address); + } + + @Test + public void testNewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //checks that we have appropriately sent the write message to server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - verify(dummyStep, times(1)).accept(any(Token.class)); + assertThat(future.get()).isEqualTo(testToken); + } - @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - - // Sets up Protocol for when a channel already exists. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) - .build(); - - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) - .build(); - - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); - - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - - //Assures that the channel has a succeeded connectionFuture. - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, ""); + //setup + setupExistingProtocol(); + setupSteps(); + setupChannel(); + setupExistingChannelToken(); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -182,21 +191,20 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); - Object msg = channel.readOutbound(); - - while (msg == null) { - msg = channel.readOutbound(); - } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked - // as a success - verify(dummyStep, times(1)).accept(any(Token.class)); + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); } } From 86261f0457440bd3802fe1812c1b5e38da207277 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 057/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From 6878d12b9554ecb06276f2e47fa15eb0a92b0a17 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:54:13 -0400 Subject: [PATCH 058/337] Updated WebWhois tests. --- .../blackbox/ProbingActionTest.java | 56 +++--- .../blackbox/ProbingSequenceTest.java | 183 ++++++++++++++++++ .../monitoring/blackbox/ProbingStepTest.java | 3 +- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 93 +++++++-- .../monitoring/blackbox/TokenTest.java | 13 +- .../blackbox/handlers/ConversionHandler.java | 2 +- .../blackbox/handlers/NettyRule.java | 12 +- .../handlers/SslClientInitializerTest.java | 46 ++--- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 159 ++++++++------- 11 files changed, 422 insertions(+), 157 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index cbcf2fc82b0..162044c2036 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -83,31 +84,31 @@ public class ProbingActionTest { /** Sets up a {@link Protocol} corresponding to when a new connection is created */ private void setupNewChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(false) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) .build(); } /** Sets up a {@link Protocol} corresponding to when a new connection exists */ private void setupExistingChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(true) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(true) .build(); } - /** Sets up a {@link NewChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ private void setupNewChannelAction() { - newChannelAction = NewChannelAction.builder() - .bootstrap(bootstrap) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") - .address(address) + newChannelAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") + .setAddress(address) .build(); } @@ -115,25 +116,25 @@ private void setupChannel() { channel = new EmbeddedChannel(); } - /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ExistingChannelAction.builder() - .channel(channel) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") + existingChannelAction = ProbingAction.builder() + .setChannel(channel) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") .build(); } @Test - public void testBehavior_existingChannel() { + public void testBehavior_existingChannel() throws InternalException { //setup setupChannel(); setupExistingChannelProtocol(); - setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); + setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -147,6 +148,7 @@ public void testBehavior_existingChannel() { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -156,9 +158,9 @@ public void testBehavior_existingChannel() { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - setupNewChannelAction(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + setupNewChannelAction(); ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2b0559514a2..681a5346d55 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,5 +1,188 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; + +import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; +import java.net.SocketAddress; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) public class ProbingSequenceTest { + private final static String TEST_HOST = "TEST_HOST"; + + + private Bootstrap dummyBootstrap = new Bootstrap(); + private Token testToken = new ProbingSequenceTestToken(); + + /** + * Custom {@link ProbingStep} subclass that acts as a mock + * step, so we can test how well {@link ProbingSequence} builds + * a linked list of {@link ProbingStep}s from their {@link Builder}s. + */ + private static class TestStep extends ProbingStep { + private Bootstrap bootstrap; + private String marker; + + /** We implement all abstract methods to simply return null, as we have no use for them here. */ + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + SocketAddress address() { + return null; + } + + /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + /** + * Builder for {@link TestStep}, that extends {@link ProbingStep.Builder} so that these can be + * input into the {@link ProbingSequence.Builder}. + */ + public static class Builder extends ProbingStep.Builder { + /** We test to see if we accurately add the right bootstrap to all {@link ProbingStep}s/ */ + private Bootstrap bootstrap; + + /** We also mark each step in order to ensure that when running, they are arranged in the right order. */ + private String marker; + + @Override + public ProbingStep.Builder setDuration(Duration value) { + return this; + } + + @Override + public ProbingStep.Builder setProtocol(Protocol value) { + return this; + } + + @Override + public ProbingStep.Builder setMessageTemplate(OutboundMessageType value) { + return null; + } + + @Override + public ProbingStep.Builder setAddress(SocketAddress address) { + return null; + } + + @Override + public ProbingStep.Builder setBootstrap(Bootstrap value) { + bootstrap = value; + return this; + } + + public ProbingStep.Builder addMarker(String value) { + marker = value; + return this; + } + + @Override + public ProbingStep build() { + return new TestStep(bootstrap, marker); + } + } + private TestStep(Bootstrap bootstrap, String marker) { + this.bootstrap = bootstrap; + this.marker = marker; + } + + /** + * On a call to accept, we modify the token to reflect what the current step is, so we can get + * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated + * in order. + */ + @Override + public void accept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + if (!isLastStep) { + nextStep().accept(token); + } else { + ((TestStep)nextStep()).specialAccept(token); + } + } + + /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ + public void specialAccept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + return; + } + } + + @Test + public void testSequenceBasicConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("firstsecondthirdfirst"); + } + + @Test + public void testSequenceAdvancedConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(thirdStepBuilder) + .addStep(secondStepBuilder) + .markFirstRepeated() + .addStep(firstStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("thirdsecondfirstsecond"); + } + @Test + public void testSequenceConstruction_Failure() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + assertThrows(AssertionError.class, () -> { + ProbingSequence sequence = new ProbingSequence.Builder() + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .setBootstrap(dummyBootstrap) + .build(); + }); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 090753014e4..ee38e7cdf74 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -21,7 +21,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; @@ -47,7 +46,7 @@ import org.junit.Test; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { +public class ProbingStepTest { /** Basic Constants necessary for tests */ private final String ADDRESS_NAME = "TEST_ADDRESS"; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 06b19ea3607..337d755e971 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -93,11 +93,11 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 8d1722c9625..161304c1f04 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,9 +17,11 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -37,6 +39,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; +import java.net.Socket; +import java.net.SocketAddress; +import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -141,26 +146,67 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } + + @Override + public OutboundMessageType modifyMessage(String... args) throws InternalException { + message = args[0]; + return this; + } + + @Override + public String name() { + return "Test Message of: " + this.toString(); + } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static class TestStep extends ProbingStep { + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .setAddress(address) + .build(); - public TestStep(Protocol protocol, String testMessage, LocalAddress address) { - super(protocol, new DuplexMessageTest(testMessage)); - this.address = address; - this.duration = Duration.ZERO; - } + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { - super(protocol, new DuplexMessageTest()); - future = new DefaultPromise(eventLoopGroup.next()) {}; - duration = Duration.ZERO; + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; + } + + @Nullable + @Override + SocketAddress address() { + return null; } @Override @@ -170,11 +216,16 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } + + @Override + public String toString() { + return "Dummy Step"; + } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - private String host; + protected String host; protected TestToken(String host) { this.host = host; @@ -221,6 +272,22 @@ public Channel channel() { } } + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..67963805733 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,10 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; @@ -34,20 +35,20 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..a8506a996a9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -37,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b6b5e8fbe0c..b38c1911940 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; @@ -89,7 +90,8 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - ProbingAction probingAction, + Protocol protocol, + String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -109,7 +111,9 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROBING_ACTION_KEY, probingAction); + .attr(PROTOCOL_KEY, protocol) + .attr(REMOTE_ADDRESS_KEY, host); + channel = b.connect(localAddress).syncUninterruptibly().channel(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 469c62a8f75..83c8e132f07 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,17 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ExistingChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; @@ -45,7 +46,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; -import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,8 +67,6 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); - /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -93,15 +91,12 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .persistentConnection(false) - .build(); - - private ProbingAction probingAction; + private final static Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -113,23 +108,13 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } - private void setupProbingAction(Channel channel) { - probingAction = ExistingChannelAction.builder() - .delay(Duration.ZERO) - .host(SSL_HOST) - .channel(channel) - .outboundMessage(DEFAULT_MESSAGE) - .protocol(PROTOCOL) - .build(); - } - @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - setupProbingAction(channel); - channel.attr(PROBING_ACTION_KEY).set(probingAction); + channel.attr(PROTOCOL_KEY).set(PROTOCOL); + channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -160,8 +145,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -189,8 +173,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -219,8 +202,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 518bb9ba686..e170fad8b8c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox.handlers; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index d8a672758da..72d5d5078df 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,21 +15,21 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; @@ -65,6 +65,14 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); + private static final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of()) + .setName("test_protocol") + .setPersistentConnection(false) + .setPort(HTTPS_PORT) + .build(); + private LocalAddress address; private EmbeddedChannel channel; @@ -75,30 +83,38 @@ public class WebWhoisActionHandlerTest { private void generateLocalAddress() { address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); } + /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port) { + private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of(actionHandlerProvider)) - .persistentConnection(false) + .setName(name) + .setPort(port) + .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) + .setPersistentConnection(persistentConnection) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); + private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { + actionHandler = new WebWhoisActionHandler( + bootstrap, + STANDARD_PROTOCOL, + STANDARD_PROTOCOL, + messageTemplate, + 80, + 443 + ); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); setupProbingActionBasic( protocol, outboundMessage, makeBootstrap(new NioEventLoopGroup(1))); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROBING_ACTION_KEY).set(probingAction); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -108,24 +124,25 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { } /**Sets up probingAction for when testing redirection */ private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(TARGET_HOST) - .address(DEFAULT_ADDRESS) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(TARGET_HOST) + .setAddress(DEFAULT_ADDRESS) + .setChannel(channel) .build(); } private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(host) - .address(address) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(host) + .setAddress(address) .build(); } @@ -136,10 +153,13 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, true); generateLocalAddress(); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + + setupChannel(initialProtocol, msg); //stores future @@ -151,7 +171,7 @@ public void testBasic_responseOk() throws Exception { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -161,15 +181,16 @@ public void testBasic_responseOk() throws Exception { //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseBad", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseBad", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -181,8 +202,7 @@ public void testBasic_responseFailure() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage - .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -194,14 +214,15 @@ public void testBasic_responseFailure() { assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseError() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseError", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseError", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -213,7 +234,7 @@ public void testBasic_responseError() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -224,27 +245,30 @@ public void testBasic_responseError() { assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_redirectCloseChannel() { //setup - HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", 0); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", 0, true); generateLocalAddress(); - setupChannel(initialProtocol, outboundMessage); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(outboundMessage); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -260,12 +284,15 @@ public void testBasic_redirectCloseChannel() { @Test public void testBasic_redirectHost() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); generateLocalAddress(); setupChannel(initialProtocol, msg); - HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); //store future @@ -275,27 +302,24 @@ public void testBasic_redirectHost() { channel.writeInbound(originalResponse); - ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - //gets changed protocol - Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); - assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); } @Test - public void testAdvanced_responseOk() { + public void testAdvanced_responseOk() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); //stores future ChannelFuture future = probingAction.call(); @@ -305,15 +329,16 @@ public void testAdvanced_responseOk() { } @Test - public void testAdvanced_responseFailure() { + public void testAdvanced_responseFailure() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); //stores future ChannelFuture future = probingAction.call(); From 9cae13c7a3814f70a1462b4132297dff3d093a63 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 059/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- prober/.gitignore | 2 +- .../registry/monitoring/blackbox/Prober.java | 9 +- .../monitoring/blackbox/ProberModule.java | 15 ++- .../monitoring/blackbox/ProbingAction.java | 96 +++++++-------- .../monitoring/blackbox/ProbingSequence.java | 24 +--- .../monitoring/blackbox/ProbingStep.java | 55 ++++++--- .../monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 49 ++++---- .../exceptions/ConnectionException.java | 5 +- .../blackbox/exceptions/FailureException.java | 15 ++- .../exceptions/InternalException.java | 30 ----- .../exceptions/ResponseException.java | 29 ----- .../blackbox/handlers/ActionHandler.java | 94 +++------------ .../handlers/WebWhoisActionHandler.java | 51 ++++---- .../blackbox/messages/HttpRequestMessage.java | 4 +- .../messages/HttpResponseMessage.java | 6 +- .../messages/OutboundMessageType.java | 7 +- .../monitoring/blackbox/tokens/Token.java | 20 +-- .../blackbox/tokens/WebWhoisToken.java | 32 +++-- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../blackbox/ProbingActionTest.java | 9 +- .../blackbox/ProbingSequenceTest.java | 114 +++--------------- .../monitoring/blackbox/ProbingStepTest.java | 4 +- .../monitoring/blackbox/TestUtils.java | 21 +--- .../monitoring/blackbox/TokenTest.java | 8 +- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 106 +++++----------- 31 files changed, 291 insertions(+), 526 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/.gitignore b/prober/.gitignore index c86568e7672..77b1e2de2de 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..307afd34d81 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +29,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 0daaf16ded4..1db97d1b581 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,14 +14,18 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.Set; import javax.inject.Singleton; import org.joda.time.Duration; @@ -33,7 +37,7 @@ public class ProberModule { /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = new Duration(4000L); + private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @@ -42,6 +46,12 @@ EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + @Provides + @Singleton + Class provideChannelClass() { + return NioSocketChannel.class; + } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides @Singleton @@ -51,6 +61,7 @@ Duration provideDuration() { /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides + @Singleton static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; @@ -66,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); + Set provideAllSequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 3f6a962b12d..67494dd5f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,25 +14,29 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -65,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -80,31 +87,18 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - @Nullable - public abstract SocketAddress address(); - - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { // Write appropriate outboundMessage to pipeline ChannelFuture channelFuture = actionHandler.getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> actionHandler.resetFuture(), - //inform ProbingStep of the status of our action future -> { if (future.isSuccess()) @@ -141,7 +135,7 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -154,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -180,19 +174,24 @@ public ChannelFuture performAction() throws InternalException { /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -210,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -221,40 +226,30 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract SocketAddress address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (address() == null) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + System.out.println("test"); + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -268,14 +263,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -293,7 +285,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2dbf48256f9..91c4165c068 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -49,32 +49,18 @@ public static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; private ProbingStep firstRepeatedStep; - private Bootstrap bootstrap; - private Token startToken; - /** - * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. - * - *

Must be called before adding {@link ProbingStep.Builder}s.

- */ - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } + private Token startToken; - /** Adds start token that activate {@link ProbingSequence}. */ - public Builder addToken(Token token) { - startToken = token; - return this; + public Builder(Token startToken) { + this.startToken = startToken; } /** - * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, * built, and pointed to by the previous {@link ProbingStep} added. */ - public Builder addStep(ProbingStep.Builder stepBuilder) { - assert (bootstrap != null); - ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + public Builder addStep(ProbingStep step) { if (currentStep == null) firstStep = step; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 47c89c72c11..ca980100067 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import java.net.SocketAddress; import java.util.function.Consumer; -import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -39,18 +37,23 @@ @AutoValue public abstract class ProbingStep implements Consumer { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ - private boolean isLastStep = false; + protected boolean isLastStep = false; private ProbingStep nextStep; + /** Time delay duration between actions. */ abstract Duration duration(); + + /** {@link Protocol} type for this step. */ abstract Protocol protocol(); + + /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ abstract OutboundMessageType messageTemplate(); + + /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ abstract Bootstrap bootstrap(); - @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -63,8 +66,6 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); - public abstract Builder setAddress(SocketAddress address); - public abstract ProbingStep build(); } @@ -85,18 +86,18 @@ ProbingStep nextStep() { } /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws InternalException { + private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) .setProtocol(protocol()) .setOutboundMessage(message) - .setHost(token.getHost()) - .setBootstrap(bootstrap()) - .setAddress(address()); + .setHost(token.host()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); + else + probingActionBuilder.setBootstrap(bootstrap()); return probingActionBuilder.build(); } @@ -107,44 +108,58 @@ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } + /** + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. + * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

+ */ @Override public void accept(Token token) { ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - //call the created action ChannelFuture future; - try { + //call the generated action future = currentAction.call(); - - } catch(InternalException e) { + } catch(UndeterminedStateException e) { + //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); + + //Move on to next step in ProbingSequence nextStep.accept(generateNextToken(token)); return; } - //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - //If the next step maintains the connection, pass on the channel from this + } else { + //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index b0342c74b7d..92470ef62c8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -29,7 +29,7 @@ public abstract class Protocol { /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - abstract String name(); + public abstract String name(); public abstract int port(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dcc9635beaa..c5e41fea38b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,6 +18,7 @@ import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,6 +27,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; @@ -44,11 +46,10 @@ @Module public class WebWhoisModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - private static final String DOMAIN_PREFIX = "whois.nic."; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; + private static final String HTTP_PROTOCOL_NAME = "http"; + private static final String HTTPS_PROTOCOL_NAME = "https"; /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; @@ -68,16 +69,14 @@ public class WebWhoisModule { /** {@link Provides} standard WebWhois sequence. */ @Provides - @WebWhoisProtocol + @Singleton + @IntoSet ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, - WebWhoisToken webWhoisToken, - @WebWhoisProtocol Bootstrap bootstrap) { + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { - return new ProbingSequence.Builder() - .addToken(webWhoisToken) - .setBootstrap(bootstrap) - .addStep(probingStepBuilder) + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) .build(); } @@ -85,15 +84,18 @@ ProbingSequence provideWebWhoisSequence( /** {@link Provides} only step used in WebWhois sequence. */ @Provides @WebWhoisProtocol - static ProbingStep.Builder provideWebWhoisStepBuilder( + static ProbingStep provideWebWhoisStep( @HttpWhoisProtocol Protocol httpWhoisProtocol, + @WebWhoisProtocol Bootstrap bootstrap, HttpRequestMessage messageTemplate, Duration duration) { return ProbingStep.builder() .setProtocol(httpWhoisProtocol) + .setBootstrap(bootstrap) .setMessageTemplate(messageTemplate) - .setDuration(duration); + .setDuration(duration) + .build(); } /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @@ -126,13 +128,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** {@link Provides} the prefix where we probe: "prefix.tld". */ - @Provides - @Named("Web-WHOIS-Prefix") - String provideWhoisPrefix() { - return DOMAIN_PREFIX; - } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @@ -187,10 +182,12 @@ static SslClientInitializer provideSslClientInitializer(SslPro @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + static Bootstrap provideBootstrap( + EventLoopGroup eventLoopGroup, + Class channelClass){ return new Bootstrap() .group(eventLoopGroup) - .channel(NioSocketChannel.class); + .channel(channelClass); } @Provides @@ -210,13 +207,13 @@ ImmutableList provideTopLevelDomains() { @Provides @HttpWhoisProtocol int provideHttpWhoisPort() { - return httpWhoIsPort; + return HTTP_WHOIS_PORT; } @Provides @HttpsWhoisProtocol int provideHttpsWhoisPort() { - return httpsWhoIsPort; + return HTTPS_WHOIS_PORT; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index be3d725c833..adb833ec629 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,9 +15,10 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is ERROR. + * Subclass of {@link UndeterminedStateException} that represents all instances when + * the action performed failed due to an issue in the connection with the server. */ -public class ConnectionException extends Exception { +public class ConnectionException extends UndeterminedStateException { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 9f716bb2589..36687e7ac82 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,5 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.exceptions; +/** + * Base exception class for all instances when the status of the action performed is FAILURE. + */ +public class FailureException extends Exception { + + public FailureException(String msg) { + super(msg); + } + + public FailureException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index e397393b4e9..0c9e93cc6dd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,13 +14,11 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -33,7 +31,7 @@ * messages that implement the {@link InboundMessageType} interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

@@ -44,111 +42,59 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); - - } else if (cause instanceof InternalException){ - //For an internal error, metrics should not be collected, so we log what caused this, and - //inform the ProbingStep the Prober had an internal error on this action - logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - - //As this was an internal error, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } else { - //In the case of any other kind of error, we assume it is some type of connection ERROR, - //so we treat it as such: + //On UndeterminedStateException, we know the response type is an error. - status = ResponseType.ERROR; - - logger.atInfo().log(cause.getMessage()); - finished.setSuccess(); + //Since it wasn't a success, we still log what caused the ERROR + logger.atWarning().log(cause.getMessage()); + finished.setFailure(cause); + //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } - - /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ - @VisibleForTesting - ResponseType getStatus() { - return status; - } -} - +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 69d5b7f1603..1ec4e314813 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -22,13 +22,12 @@ import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -62,27 +61,17 @@ public class WebWhoisActionHandler extends ActionHandler { /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ private final HttpRequestMessage requestMessage; - /** Default port for http. */ - private int httpPort; - - /** default port for https. */ - private int httpsPort; - @Inject public WebWhoisActionHandler( @WebWhoisProtocol Bootstrap bootstrap, @HttpWhoisProtocol Protocol httpWhoisProtocol, @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage, - @HttpWhoisProtocol int httpPort, - @HttpsWhoisProtocol int httpsPort) { + HttpRequestMessage requestMessage) { this.bootstrap = bootstrap; this.httpWhoisProtocol = httpWhoisProtocol; this.httpsWhoisProtocol = httpsWhoisProtocol; this.requestMessage = requestMessage; - this.httpPort = httpPort; - this.httpsPort = httpsPort; } @@ -93,7 +82,7 @@ public WebWhoisActionHandler( */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -112,7 +101,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -123,12 +112,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; - if (newPort == httpPort) { + if (url.getProtocol().equals(httpWhoisProtocol.name())) { newProtocol = httpWhoisProtocol; - } else if (newPort == httpsPort) { + } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -143,34 +132,38 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) .setHost(newHost) .build(); - //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); - //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..b4c01d06a8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,12 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..f1b2d6ac6a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -25,11 +25,7 @@ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { - super(version, status); - } - - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index be6c872cc3e..6e3da3f69d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,7 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline @@ -22,8 +22,9 @@ public interface OutboundMessageType { /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - public OutboundMessageType modifyMessage(String... args) throws InternalException; + OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - public String name(); + @Override + String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dd1882b5686..dab5851e8d8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,16 +14,18 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.ProbingSequence; +import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} - * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} + * in a single loop of a {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * in a {@link ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -31,17 +33,21 @@ */ public abstract class Token { - /** {@link Channel} that always starts out as null. */ + /** + * {@link Channel} that always starts out as null. Once a persistent connection + * is made (such as EPP), that channel is stored in the token and passed on to + * later steps in the sequence until a new loop begins. + */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String getHost(); + public abstract String host(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 2847e5ce0eb..bb06ee89db6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import javax.inject.Inject; import javax.inject.Named; @@ -33,42 +33,38 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final String prefix; + private final static String PREFIX = "whois.nic."; /** {@link ImmutableList} of all top level domains to be probed. */ - private final ImmutableList topLevelDomains; + private final Iterator topLevelDomainsIterator; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private int domainsIndex; + private String currentDomain; @Inject - public WebWhoisToken( - @Named("Web-WHOIS-Prefix") String prefix, - @WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { - domainsIndex = 0; - this.prefix = prefix; - this.topLevelDomains = topLevelDomains; + topLevelDomainsIterator = topLevelDomains.iterator(); + currentDomain = topLevelDomainsIterator.next(); } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - domainsIndex += 1; - domainsIndex %= topLevelDomains.size(); + currentDomain = topLevelDomainsIterator.next(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { - return original.modifyMessage(getHost()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + return original.modifyMessage(host()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String getHost() { - return prefix + topLevelDomains.get(domainsIndex); + public String host() { + return PREFIX + currentDomain; } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( { - ProbingSequence sequence = new ProbingSequence.Builder() - .addStep(firstStepBuilder) - .addStep(secondStepBuilder) - .addStep(thirdStepBuilder) - .addToken(testToken) - .setBootstrap(dummyBootstrap) - .build(); - }); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index ee38e7cdf74..7bba9d66782 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.TestUtils.dummyStep; import static google.registry.monitoring.blackbox.TestUtils.testStep; import static google.registry.testing.JUnitBackports.assertThrows; @@ -90,7 +91,7 @@ public class ProbingStepTest { /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ private void setupNewChannelToken() { - testToken = new NewChannelToken(""); + testToken = new NewChannelToken(ADDRESS_NAME); } /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ @@ -101,6 +102,7 @@ private void setupExistingChannelToken() { /** Sets up an embedded channel to contain the two handlers we created already */ private void setupChannel() { channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 161304c1f04..68bdd0bcef0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,7 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,8 +26,6 @@ import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpMessage; @@ -39,7 +37,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; -import java.net.Socket; import java.net.SocketAddress; import javax.annotation.Nullable; import javax.inject.Provider; @@ -148,15 +145,10 @@ public String toString() { } @Override - public OutboundMessageType modifyMessage(String... args) throws InternalException { + public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { message = args[0]; return this; } - - @Override - public String name() { - return "Test Message of: " + this.toString(); - } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ @@ -166,7 +158,6 @@ public static ProbingStep testStep(Protocol protocol, String testMessage, Bootst .setDuration(Duration.ZERO) .setMessageTemplate(new DuplexMessageTest(testMessage)) .setBootstrap(bootstrap) - .setAddress(address) .build(); } @@ -203,12 +194,6 @@ Bootstrap bootstrap() { return null; } - @Nullable - @Override - SocketAddress address() { - return null; - } - @Override public void accept(Token token) { future.setSuccess(token); @@ -241,7 +226,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String getHost() { + public String host() { return host; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index 67963805733..295bb809a13 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -17,12 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -37,7 +35,7 @@ public class TokenTest { private static String TEST_STARTER = "starter"; private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { @@ -49,7 +47,7 @@ public void testWebToken_MessageModificationSuccess() { try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index e170fad8b8c..3ecbdcc0d06 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -29,7 +29,7 @@ public class TestActionHandler extends ActionHandler { @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 72d5d5078df..2483bd65b1f 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,21 +15,23 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; @@ -64,11 +66,9 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); private static final Protocol STANDARD_PROTOCOL = Protocol.builder() .setHandlerProviders(ImmutableList.of()) - .setName("test_protocol") + .setName("http") .setPersistentConnection(false) .setPort(HTTPS_PORT) .build(); @@ -80,8 +80,10 @@ public class WebWhoisActionHandlerTest { private ProbingAction probingAction; private Provider actionHandlerProvider; - private void generateLocalAddress() { - address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + private String generateLocalAddress(String addressString) { + String modifiedAddress = addressString + System.currentTimeMillis(); + address = new LocalAddress(modifiedAddress); + return modifiedAddress; } /** Creates default protocol with empty list of handlers and specified other inputs */ @@ -100,9 +102,7 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT bootstrap, STANDARD_PROTOCOL, STANDARD_PROTOCOL, - messageTemplate, - 80, - 443 + messageTemplate ); actionHandlerProvider = new TestProvider<>(actionHandler); } @@ -111,10 +111,8 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - setupProbingActionBasic( - protocol, - outboundMessage, - makeBootstrap(new NioEventLoopGroup(1))); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -123,26 +121,23 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } /**Sets up probingAction for when testing redirection */ - private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) .setHost(TARGET_HOST) - .setAddress(DEFAULT_ADDRESS) .setChannel(channel) .build(); } - private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) .setBootstrap(bootstrap) - .setHost(host) - .setAddress(address) + .setHost(addressString) .build(); } @@ -157,8 +152,6 @@ public void testBasic_responseOk() throws Exception { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseOk", 0, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); @@ -185,13 +178,12 @@ public void testBasic_responseOk() throws Exception { } @Test - public void testBasic_responseFailure() { + public void testBasic_responseFailure_badRequest() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseBad", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -211,19 +203,18 @@ public void testBasic_responseFailure() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testBasic_responseError() { + public void testBasic_responseFailure_badURL() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseError", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -243,9 +234,9 @@ public void testBasic_responseError() { //assesses that listener is triggered, and event is success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException); } @Test @@ -257,7 +248,6 @@ public void testBasic_redirectCloseChannel() { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("redirectHttp", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -282,44 +272,15 @@ public void testBasic_redirectCloseChannel() { } @Test - public void testBasic_redirectHost() { + public void testAdvanced_responseOk() throws UndeterminedStateException { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); - HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); - - - //store future - ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); - - - channel.writeInbound(originalResponse); - - Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - } - - @Test - public void testAdvanced_responseOk() throws InternalException { - //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); @@ -329,22 +290,21 @@ public void testAdvanced_responseOk() throws InternalException { } @Test - public void testAdvanced_responseFailure() throws InternalException { + public void testAdvanced_responseFailure() throws UndeterminedStateException { //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); + String host = generateLocalAddress(TARGET_HOST); HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(bootstrap, msg); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + assertThrows(FailureException.class, future::syncUninterruptibly); } } From 13ed64532bea02411d520e4a78a6a65b6ce17e87 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:48:33 -0400 Subject: [PATCH 060/337] SpotlessApply run to fix style issues --- prober/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index 77b1e2de2de..c86568e7672 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From 4182054c11388b4cccfd6b94924807620284a42a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:28:40 -0400 Subject: [PATCH 061/337] Added license header and newline where appropriate. --- prober/build.gradle | 1 + .../monitoring/blackbox/ProbingAction.java | 1 - .../blackbox/handlers/ActionHandler.java | 2 +- .../monitoring/blackbox/ProbingSequenceTest.java | 14 ++++++++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 26d44c0a465..70b8e2a6b8b 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -35,6 +35,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] + compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 67494dd5f78..a8740e21c20 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -240,7 +240,6 @@ public ProbingAction build() { InetAddress hostAddress = InetAddress.getByName(host()); address = new InetSocketAddress(hostAddress, protocol().port()); } catch (UnknownHostException e) { - System.out.println("test"); address = new LocalAddress(host()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 0c9e93cc6dd..8a108b81006 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -97,4 +97,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } -} \ No newline at end of file +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2a8d5ebe233..8d9e45c6a66 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; From 13cbc8e700dd905aa36770fbc4fd7175f55ffadf Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 062/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/ProbingStepTest.java | 1 - .../blackbox/TestServers/WebWhoisServer.java | 3 +- .../monitoring/blackbox/TestUtils.java | 35 +------------------ .../blackbox/handlers/ConversionHandler.java | 5 ++- .../blackbox/handlers/NettyRule.java | 4 ++- 5 files changed, 10 insertions(+), 38 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 7bba9d66782..73b104ae5dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -174,7 +174,6 @@ public void testNewChannel() throws Exception { //checks that when the future is successful, we pass down the requisite token assertThat(future.get()).isEqualTo(testToken); - } @Test diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 337d755e971..e7f125bb906 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; @@ -80,7 +81,7 @@ static class RedirectHandler extends ChannelDuplexHandler { /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 68bdd0bcef0..cc8e1512fe9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; @@ -28,17 +27,13 @@ import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpMethod;; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; import java.net.SocketAddress; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -272,33 +267,5 @@ public void addToHost(String suffix) { } } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index a8506a996a9..196141bb875 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b38c1911940..1d14cf131e6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -26,6 +26,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.ProbingActionTest; +import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; @@ -54,7 +56,7 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { From 3ceaf468ddbcd15a1386a85eff90b237b3704e2c Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 5 Aug 2019 16:16:36 -0400 Subject: [PATCH 063/337] Refactored ProbingAction to minimize number of unnecessary methods --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 4 +- .../monitoring/blackbox/ProbingAction.java | 160 ++++++++---------- .../monitoring/blackbox/ProbingStep.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 4 +- .../blackbox/handlers/ActionHandler.java | 2 +- .../handlers/WebWhoisActionHandler.java | 7 +- .../blackbox/messages/HttpRequestMessage.java | 5 +- .../blackbox/ProbingActionTest.java | 130 +++++++------- .../blackbox/ProbingSequenceTest.java | 25 ++- .../monitoring/blackbox/ProbingStepTest.java | 6 + .../monitoring/blackbox/TestUtils.java | 2 +- .../handlers/WebWhoisActionHandlerTest.java | 9 +- 13 files changed, 176 insertions(+), 183 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 307afd34d81..e12d1f0f522 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; import java.util.Set; @@ -29,7 +30,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); + Set sequences = proberComponent.sequences(); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 1db97d1b581..fb83b236b69 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -49,7 +49,7 @@ EventLoopGroup provideEventLoopGroup() { /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides @Singleton - Class provideChannelClass() { + Class provideChannelClazz() { return NioSocketChannel.class; } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @@ -77,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - Set provideAllSequences(); + Set sequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index a8740e21c20..25c3a1c17d6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -33,10 +33,8 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -69,6 +67,8 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -85,6 +85,7 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ @@ -94,108 +95,89 @@ public abstract class ProbingAction implements Callable { public abstract String host(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } - /** - * The method that performs the work of the actual action. + * Performs the work of the actual action * - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ *

First, checks if channel is active by setting a listener to perform the bulk of the work + * when the connection future is successful.

+ * + *

Once the connection is successful, we establish which of the handlers in the pipeline is + * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when + * we receive an expected response from the server.

+ * + *

Next, we set a timer set to a specified delay. After the delay has passed, we send the + * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, + * we inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - - //ChannelPromise that we use to inform ProbingStep when we are finished. - ChannelPromise finished = channel().newPromise(); - - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - - return finished; - } /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws UndeterminedStateException { + public ChannelFuture call() { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); + + //Ensures channel has been set up with connection future as an attribute + checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + //When connection is established call super.call and set returned listener to success channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { + (ChannelFuture connectionFuture) -> { + if (connectionFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); + ActionHandler actionHandler; + try { + actionHandler = channel().pipeline().get(ActionHandler.class); + } catch (ClassCastException e) { + //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); + } + + ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> { + if (future.isSuccess()) { + finished.setSuccess(); + } else { + finished.setFailure(future.cause()); + } + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) { + logger.atInfo() + .log("Closed stale channel. Moving on to next ProbingStep"); + } else { + logger.atWarning() + .log( + "Could not close channel. Stale connection still exists."); + } + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); } else { //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( + logger.atSevere().withCause(connectionFuture.cause()).log( "Cannot connect to relay channel for %s channel: %s.", protocol().name(), this.channel()); ChannelFuture unusedFuture = channel().close(); @@ -228,7 +210,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract Protocol protocol(); - abstract Optional channel(); + abstract Channel channel(); abstract String host(); @@ -243,11 +225,11 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { + if (channel() == null) { bootstrap.handler( new ChannelInitializer() { @Override diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index ca980100067..3df536a9478 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -135,7 +135,7 @@ public void accept(Token token) { try { //call the generated action future = currentAction.call(); - } catch(UndeterminedStateException e) { + } catch(Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index c5e41fea38b..2e640338511 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -184,10 +184,10 @@ static SslClientInitializer provideSslClientInitializer(SslPro @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClass){ + Class channelClazz){ return new Bootstrap() .group(eventLoopGroup) - .channel(channelClass); + .channel(channelClazz); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 8a108b81006..55c9123e3a5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -46,7 +46,7 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler testHandlerProvider = new TestProvider<>(testHandler); private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - private ProbingAction newChannelAction; - private ProbingAction existingChannelAction; - private EmbeddedChannel channel; - private Protocol protocol; - /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** Sets up a {@link Protocol} corresponding to when a new connection is created */ - private void setupNewChannelProtocol() { - protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - } - /** Sets up a {@link Protocol} corresponding to when a new connection exists */ - private void setupExistingChannelProtocol() { - protocol = Protocol.builder() + + + + @Test + public void testBehavior_existingChannel() throws UndeterminedStateException { + //setup + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up a Protocol corresponding to when a connection exists. + Protocol protocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) .build(); - } - - /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ - private void setupNewChannelAction() { - newChannelAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - } - - private void setupChannel() { - channel = new EmbeddedChannel(); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ - private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ProbingAction.builder() + // Sets up a ProbingAction that creates a channel using test specified attributes. + ProbingAction action = ProbingAction.builder() .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) .setHost("") .build(); - } - - @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { - //setup - setupChannel(); - setupExistingChannelProtocol(); - channel.pipeline().addLast(conversionHandler); - channel.pipeline().addLast(testHandler); - setupExistingChannelAction(channel); + //tests main function of ProbingAction + ChannelFuture future = action.call(); - ChannelFuture future = existingChannelAction.call(); - - //Ensures that we pass in the right message to the channel and haven't marked the future as success yet - Object msg = channel.readOutbound(); + //Obtains the outboundMessage passed through pipeline after delay + Object msg = null; + while (msg == null) { + msg = channel.readOutbound(); + } + //tests the passed message is exactly what we expect assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - assertThat(response).isEqualTo(TEST_MESSAGE); - assertThat(future.isSuccess()).isFalse(); + String request = ((ByteBuf) msg).toString(UTF_8); + assertThat(request).isEqualTo(TEST_MESSAGE); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -158,18 +122,40 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { @Test public void testSuccess_newChannel() throws Exception { //setup - setupNewChannelProtocol(); + + LocalAddress address = new LocalAddress(ADDRESS_NAME); + Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + // Sets up a Protocol corresponding to when a new connection is created. + Protocol protocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) + .build(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - setupNewChannelAction(); - ChannelFuture future = newChannelAction.call(); + + // Sets up a ProbingAction with existing channel using test specified attributes. + ProbingAction action = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) + .build(); + + //tests main function of ProbingAction + ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.sync(); + future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()); + assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 8d9e45c6a66..e5f91a300d6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -18,27 +18,44 @@ import static google.registry.testing.JUnitBackports.assertThrows; import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.TestUtils.TestToken; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import java.net.SocketAddress; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; @RunWith(JUnit4.class) public class ProbingSequenceTest { private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new ProbingSequenceTestToken(); + private Token testToken = new TestToken("") { + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + }; + private void setupMock(ProbingStep mock, ProbingStep nextStep) { + Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + } /** * Custom {@link ProbingStep} subclass that acts as a mock * step, so we can test how well {@link ProbingSequence} builds * a linked list of {@link ProbingStep}s from their {@link Builder}s. */ + private static class TestStep extends ProbingStep { private String marker; @@ -92,9 +109,9 @@ public void specialAccept(Token token) { @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 73b104ae5dc..256eeb0b29d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -45,6 +45,7 @@ import javax.inject.Provider; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ public class ProbingStepTest { @@ -191,6 +192,11 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); + Object msg = channel.readOutbound(); + + while (msg == null) { + msg = channel.readOutbound(); + } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index cc8e1512fe9..ef9926a7620 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -204,7 +204,7 @@ public String toString() { } /** Basic outline for {@link Token} instances to be used in tests */ - private static abstract class TestToken extends Token { + static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 2483bd65b1f..5fa39b1da83 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -41,7 +41,6 @@ import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; import org.joda.time.Duration; @@ -156,7 +155,7 @@ public void testBasic_responseOk() throws Exception { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); @@ -187,7 +186,7 @@ public void testBasic_responseFailure_badRequest() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -218,7 +217,7 @@ public void testBasic_responseFailure_badURL() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -251,7 +250,7 @@ public void testBasic_redirectCloseChannel() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early From b18f6c2041a07fe003d091b9fe6ad64c03ea0c1f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 15:45:32 -0400 Subject: [PATCH 064/337] Modified tests for WebWhois according to changes suggested by laijiang. --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 2 - .../monitoring/blackbox/ProbingAction.java | 1 - .../monitoring/blackbox/WebWhoisModule.java | 10 +- .../blackbox/ProbingActionTest.java | 20 +- .../blackbox/ProbingSequenceTest.java | 120 ++++------- .../monitoring/blackbox/ProbingStepTest.java | 187 ++++++++--------- .../blackbox/TestServers/TestServer.java | 38 ---- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 142 +------------ .../monitoring/blackbox/TokenTest.java | 59 ------ .../blackbox/handlers/ConversionHandler.java | 6 +- .../blackbox/handlers/NettyRule.java | 46 +++- .../handlers/SslClientInitializerTest.java | 5 - .../blackbox/handlers/TestActionHandler.java | 7 +- .../handlers/WebWhoisActionHandlerTest.java | 197 +++++++----------- .../blackbox/messages/TestMessage.java | 4 + 17 files changed, 264 insertions(+), 589 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index e12d1f0f522..5ca423c29cc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -30,7 +29,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.sequences(); + ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index fb83b236b69..f9db4865f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,11 +14,9 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 25c3a1c17d6..0265390fafe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -138,7 +138,6 @@ public ChannelFuture call() { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); timer.newTimeout(timeout -> { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 2e640338511..de041afad38 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,14 +17,11 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -33,10 +30,7 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index b5d8f7599c4..ec5ee5d77ec 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,17 +20,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -39,9 +37,9 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; import javax.inject.Provider; import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,10 +72,9 @@ public class ProbingActionTest { public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - + @Ignore @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { + public void testBehavior_existingChannel() { //setup EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -95,7 +92,7 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost("") .build(); @@ -112,6 +109,9 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { String request = ((ByteBuf) msg).toString(UTF_8); assertThat(request).isEqualTo(TEST_MESSAGE); + // Ensures that we haven't marked future as done until response is received. + assertThat(future.isDone()).isFalse(); + //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); assertThat(future.isSuccess()).isTrue(); @@ -143,7 +143,7 @@ public void testSuccess_newChannel() throws Exception { .setBootstrap(bootstrap) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost(ADDRESS_NAME) .build(); @@ -151,7 +151,7 @@ public void testSuccess_newChannel() throws Exception { ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index e5f91a300d6..5c4452df7b3 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -15,17 +15,11 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; -import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; -import google.registry.monitoring.blackbox.TestUtils.TestToken; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import java.net.SocketAddress; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,85 +27,31 @@ @RunWith(JUnit4.class) public class ProbingSequenceTest { - private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new TestToken("") { - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - }; - - private void setupMock(ProbingStep mock, ProbingStep nextStep) { - Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + private ProbingStep setupMock() { + ProbingStep mock = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(mock).nextStep(); + return mock; } - /** - * Custom {@link ProbingStep} subclass that acts as a mock - * step, so we can test how well {@link ProbingSequence} builds - * a linked list of {@link ProbingStep}s from their {@link Builder}s. - */ - - private static class TestStep extends ProbingStep { - private String marker; - - /** We implement all abstract methods to simply return null, as we have no use for them here. */ - @Override - Duration duration() { - return null; - } - @Override - Protocol protocol() { - return null; - } + private static class Wrapper { - @Override - OutboundMessageType messageTemplate() { - return null; - } + T data; - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ - @Override - Bootstrap bootstrap() { - return null; - } - - public TestStep(String marker) { - this.marker = marker; - } - - /** - * On a call to accept, we modify the token to reflect what the current step is, so we can get - * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated - * in order. - */ - @Override - public void accept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - if (!isLastStep) { - nextStep().accept(token); - } else { - ((TestStep)nextStep()).specialAccept(token); - } - } - - /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ - public void specialAccept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - return; + public Wrapper(T data) { + this.data = data; } } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = Mockito.mock(ProbingStep.class); - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) @@ -119,16 +59,25 @@ public void testSequenceBasicConstruction_Success() { .addStep(thirdStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(thirdStep); + assertThat(thirdStep.nextStep()).isEqualTo(firstStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); + assertThat(wrapper.data).isTrue(); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(thirdStep) @@ -137,9 +86,16 @@ public void testSequenceAdvancedConstruction_Success() { .addStep(firstStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(firstStep); + assertThat(thirdStep.nextStep()).isEqualTo(secondStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); + assertThat(wrapper.data).isTrue(); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 256eeb0b29d..91a113940e8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,18 +11,19 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.TestUtils.dummyStep; -import static google.registry.monitoring.blackbox.TestUtils.testStep; -import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; import google.registry.monitoring.blackbox.TestUtils.TestProvider; @@ -30,19 +31,20 @@ import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; +import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; @@ -51,18 +53,18 @@ public class ProbingStepTest { /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final static String ADDRESS_NAME = "TEST_ADDRESS"; + private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final static int PROTOCOL_PORT = 0; + private final static String TEST_MESSAGE = "TEST_MESSAGE"; + private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -73,117 +75,108 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(ADDRESS_NAME); + /** + * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} + * is called, it just marks the supplied future as succeeded, returning the requisite token. + */ + private ProbingStep dummyStep() { + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(dummyStep).nextStep(); + return dummyStep; } - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); - dummyStep = dummyStep(eventLoopGroup); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - } + @Test + public void testNewChannel() throws Exception { + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() + // Sets up Protocol for when we create a new channel. + Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); - } - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) .build(); - } - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - //there should be no next step - assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); - } + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); - @Test - public void testNewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + //Set up blackbox server that receives our messages then echoes them back to us + nettyRule.setUpServer(address); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); + verify(dummyStep, times(1)).accept(any(Token.class)); } + @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupChannel(); - setupExistingChannelToken(); + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); + + // Sets up Protocol for when a channel already exists. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) + .build(); + + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) + .build(); + + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + + // Sets up an embedded channel to contain the two handlers we created already. + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + + //Assures that the channel has a succeeded connectionFuture. + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. + Token testToken = new ExistingChannelToken(channel, ""); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -200,17 +193,13 @@ public void testWithSequence_ExistingChannel() throws Exception { //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); + //At this point, we should have received the message, so the future obtained should be marked + // as a success + verify(dummyStep, times(1)).accept(any(Token.class)); - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index a4474b6b8b5..12e25a6bc6c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -14,24 +14,16 @@ package google.registry.monitoring.blackbox.TestServers; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; - import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform @@ -65,35 +57,5 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index e7f125bb906..4da75b31c25 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -74,7 +75,7 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends ChannelDuplexHandler { + static class RedirectHandler extends SimpleChannelInboundHandler { private String redirectInput; private String destinationInput; @@ -90,8 +91,7 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - HttpRequest request = (HttpRequest) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index ef9926a7620..2567a7cc155 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,42 +16,24 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMethod;; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.concurrent.DefaultPromise; -import java.net.SocketAddress; import javax.inject.Provider; -import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { - static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -76,33 +58,13 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); + response.headers().set("content-type", "text/plain"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); return response; } @@ -121,88 +83,6 @@ public E get() { } } - /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ - public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { - - String message; - - public DuplexMessageTest() { - message = ""; - } - - public DuplexMessageTest(String msg) { - message = msg; - } - - @Override - public String toString() { - return message; - } - - @Override - public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { - message = args[0]; - return this; - } - } - - /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .build(); - - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); - } - - /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { - private DefaultPromise future; - - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; - } - - @Override - public void accept(Token token) { - future.setSuccess(token); - } - public DefaultPromise getFuture() { - return future; - } - - @Override - public String toString() { - return "Dummy Step"; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; @@ -251,21 +131,5 @@ public Channel channel() { return channel; } } - - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java deleted file mode 100644 index 295bb809a13..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) - */ -@RunWith(JUnit4.class) -public class TokenTest { - - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - - public Token webToken = new WebWhoisToken(TEST_DOMAINS); - - @Test - public void testWebToken_MessageModificationSuccess() { - //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); - - //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { - throw new RuntimeException(e); - } - - - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 196141bb875..c9d337d6ad8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -32,7 +32,7 @@ * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +40,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 1d14cf131e6..86b54d9a07d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -25,14 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -44,7 +41,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -55,7 +51,7 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + *

Code based on and almost identical to {@code NettyRule} in the proxy. * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -83,10 +79,12 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + ImmutableList.builder().add(handlers).add(echoHandler).build()); } /** Sets up a client channel connecting to the give local address. */ @@ -124,7 +122,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertThatCustomWorks(String message) throws Exception { + public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -165,6 +163,38 @@ ThrowableSubject assertThatClientRootCause() { } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** + * Saves any inbound error as the cause of the promise failure. + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 83c8e132f07..523fb228752 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -22,12 +22,7 @@ import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 3ecbdcc0d06..95b06e623d1 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -25,17 +25,16 @@ */ public class TestActionHandler extends ActionHandler { - private String receivedMessage; + private InboundMessageType receivedMessage; @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage.toString(); + receivedMessage = inboundMessage; super.channelRead0(ctx, inboundMessage); } - @Override - public String toString() { + public InboundMessageType getResponse() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 5fa39b1da83..3667f3f3d9a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -20,7 +20,6 @@ import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; -import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; @@ -28,13 +27,11 @@ import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; @@ -56,6 +53,7 @@ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -65,11 +63,12 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of()) + private final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( + null, null, null, null)))) .setName("http") .setPersistentConnection(false) - .setPort(HTTPS_PORT) + .setPort(HTTP_PORT) .build(); @@ -78,14 +77,13 @@ public class WebWhoisActionHandlerTest { private ActionHandler actionHandler; private ProbingAction probingAction; private Provider actionHandlerProvider; + private Protocol initialProtocol; + private HttpRequestMessage msg; - private String generateLocalAddress(String addressString) { - String modifiedAddress = addressString + System.currentTimeMillis(); - address = new LocalAddress(modifiedAddress); - return modifiedAddress; - } - /** Creates default protocol with empty list of handlers and specified other inputs */ + /** + * Creates default protocol with empty list of handlers and specified other inputs + */ private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() .setName(name) @@ -95,7 +93,9 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect .build(); } - /** Initializes new WebWhoisActionHandler */ + /** + * Initializes new WebWhoisActionHandler + */ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, @@ -106,12 +106,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT actionHandlerProvider = new TestProvider<>(actionHandler); } - /** Sets up testing channel with requisite attributes */ + /** + * Sets up testing channel with requisite attributes + */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -119,18 +120,9 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .group(group) .channel(LocalChannel.class); } - /**Sets up probingAction for when testing redirection */ - private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setHost(TARGET_HOST) - .setChannel(channel) - .build(); - } - private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { + private void setupProbingActionWithoutChannel(Protocol protocol, + HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) @@ -140,171 +132,124 @@ private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMess .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + private void setupLocalServer(String redirectInput, String destinationInput, + EventLoopGroup group) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testBasic_responseOk() throws Exception { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { + msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, true); + initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + } + + @Test + public void testBasic_responseOk() { + //setup + setup("", null, true); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure_badRequest() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseBad", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage( + makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same assertThat(future.cause() instanceof FailureException).isTrue(); } - @Test - public void testBasic_responseFailure_badURL() { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseError", 0, true); - setupChannel(initialProtocol, msg); - - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, and event is success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); - } @Test - public void testBasic_redirectCloseChannel() { + public void testBasic_responseFailure_badURL() { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - //checks that future has not been set to successful or a failure - assertThat(testPromise.isSuccess()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - + //assesses that listener is triggered, and event is success + assertThat(future.isDone()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + //ensures Protocol is the same + assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_responseOk() throws UndeterminedStateException { - //setup + public void testAdvanced_redirect() { + // Sets up EventLoopGroup with 1 thread to be blocking. EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + // Sets up embedded channel. + setup("", makeBootstrap(group), false); + setupChannel(initialProtocol, msg); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); - } + // Initializes LocalAddress with unique String. + String host = TARGET_HOST + System.currentTimeMillis(); + address = new LocalAddress(host); - @Test - public void testAdvanced_responseFailure() throws UndeterminedStateException { - //setup - EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); + //stores future + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); + + // Sets up the local server that the handler will be redirected to. setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + FullHttpResponse response = + new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, + HTTP_REDIRECT + host, true, false)); + + //checks that future has not been set to successful or a failure + assertThat(future.isDone()).isFalse(); + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); //assesses that we successfully received good response and protocol is unchanged - assertThrows(FailureException.class, future::syncUninterruptibly); + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index 922c3052bda..c31a9d336bd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,6 +24,10 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; + public TestMessage() { + this(""); + } + public TestMessage(String msg) { message = msg; } From 7ce3064b7d248155b798f7588eb96900f5d49390 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 16:42:43 -0400 Subject: [PATCH 065/337] Removed TestProvider from TestUtils. --- .../blackbox/ProbingActionTest.java | 7 ++-- .../monitoring/blackbox/ProbingStepTest.java | 11 +++--- .../blackbox/TestServers/TestServer.java | 3 -- .../monitoring/blackbox/TestUtils.java | 17 --------- .../handlers/WebWhoisActionHandlerTest.java | 36 ++++++------------- .../blackbox/messages/TestMessage.java | 4 --- 6 files changed, 18 insertions(+), 60 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index ec5ee5d77ec..f7857dd80f9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -64,8 +63,8 @@ public class ProbingActionTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + private Provider testHandlerProvider = () -> testHandler; + private Provider conversionHandlerProvider = () -> conversionHandler; /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -156,7 +155,7 @@ public void testSuccess_newChannel() throws Exception { future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 91a113940e8..1f09dd13553 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -90,9 +89,8 @@ private ProbingStep dummyStep() { @Test public void testNewChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when we create a new channel. Protocol testProtocol = Protocol.builder() @@ -142,9 +140,8 @@ public void testNewChannel() throws Exception { @Test public void testWithSequence_ExistingChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when a channel already exists. Protocol testProtocol = Protocol.builder() diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 12e25a6bc6c..46615a506fb 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -29,15 +29,12 @@ * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { - private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - this.localAddress = localAddress; - //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 2567a7cc155..50c60d9fc52 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -21,7 +21,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -29,7 +28,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Provider; /** Utility class for various helper methods used in testing. */ public class TestUtils { @@ -68,21 +66,6 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ - public static class TestProvider implements Provider { - - private E obj; - - public TestProvider(E obj) { - this.obj = obj; - } - - @Override - public E get() { - return obj; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 3667f3f3d9a..33eb190a66a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -25,7 +25,6 @@ import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; @@ -64,18 +63,16 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( - null, null, null, null)))) + .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( + null, null, null, null))) .setName("http") .setPersistentConnection(false) .setPort(HTTP_PORT) .build(); - private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; - private ProbingAction probingAction; private Provider actionHandlerProvider; private Protocol initialProtocol; private HttpRequestMessage msg; @@ -103,13 +100,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT STANDARD_PROTOCOL, messageTemplate ); - actionHandlerProvider = new TestProvider<>(actionHandler); + actionHandlerProvider = () -> actionHandler; } /** * Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + private void setupChannel(Protocol protocol) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -121,19 +118,8 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } - private void setupProbingActionWithoutChannel(Protocol protocol, - HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(addressString) - .build(); - } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group) { + EventLoopGroup group, LocalAddress address) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } @@ -148,7 +134,7 @@ private void setup(String hostName, Bootstrap bootstrap, boolean persistentConne public void testBasic_responseOk() { //setup setup("", null, true); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -169,7 +155,7 @@ public void testBasic_responseOk() { public void testBasic_responseFailure_badRequest() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -195,7 +181,7 @@ public void testBasic_responseFailure_badRequest() { public void testBasic_responseFailure_badURL() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -224,18 +210,18 @@ public void testAdvanced_redirect() { // Sets up embedded channel. setup("", makeBootstrap(group), false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); // Initializes LocalAddress with unique String. String host = TARGET_HOST + System.currentTimeMillis(); - address = new LocalAddress(host); + LocalAddress address = new LocalAddress(host); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group); + setupLocalServer("", host, group, address); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index c31a9d336bd..922c3052bda 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,10 +24,6 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; - public TestMessage() { - this(""); - } - public TestMessage(String msg) { message = msg; } From 572657cf5782bbe410df9f0786f4f60ec4a3031a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 09:46:27 -0400 Subject: [PATCH 066/337] Rebased to master --- .../monitoring/blackbox/handlers/ActionHandler.java | 7 +++++-- .../monitoring/blackbox/TestServers/WebWhoisServer.java | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 55c9123e3a5..eda82c59a37 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -33,8 +33,11 @@ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} - * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * of the error. If the error is an instance of a {@link FailureException} {@code finished} is + * marked as a failure with cause {@link FailureException}. If it is any other type of error, it + * is treated as an {@link UndeterminedStateException} and {@code finished} set as a failure with + * the same cause as what caused the exception. Lastly, if no error is thrown, we know the action + * completed as a success, and, as such, we mark {@code finished} as a success.

* *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 4da75b31c25..28b36190a7e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; From c5a441639f0725377fa4d7e326363b53e00a59a7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 11:26:33 -0400 Subject: [PATCH 067/337] Updated issues in rebasing --- core/src/main/java/google/registry/ui/package-info.java | 1 - core/src/main/java/google/registry/xjc/package-info.java | 1 - 2 files changed, 2 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..ddff37c6807 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -14,4 +14,3 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.ui; - diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..5b5456585cc 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -14,4 +14,3 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.xjc; - From 8ed3f4797b259e3f6e2b7473a41a8f2c5dbdeb53 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 12:33:30 -0400 Subject: [PATCH 068/337] Minor style change on prober/build.gradle --- core/src/main/java/google/registry/cron/package-info.java | 2 +- core/src/main/java/google/registry/xml/package-info.java | 2 +- prober/build.gradle | 1 - .../registry/monitoring/blackbox/handlers/ActionHandler.java | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/google/registry/cron/package-info.java b/core/src/main/java/google/registry/cron/package-info.java index 49b18ca2885..459f2513f93 100644 --- a/core/src/main/java/google/registry/cron/package-info.java +++ b/core/src/main/java/google/registry/cron/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xml/package-info.java b/core/src/main/java/google/registry/xml/package-info.java index b3f27868b91..f8e42585ecc 100644 --- a/core/src/main/java/google/registry/xml/package-info.java +++ b/core/src/main/java/google/registry/xml/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/prober/build.gradle b/prober/build.gradle index 70b8e2a6b8b..3652390d0ba 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -53,4 +53,3 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index eda82c59a37..8f2319b3d39 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -60,7 +60,7 @@ public void handlerAdded(ChannelHandlerContext ctx) { finished = ctx.newPromise(); } - /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ + /** Marks {@link ChannelPromise} as success */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { From c075964be72cfff1c25dd27c7d7cae2f84646375 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 15:11:53 -0400 Subject: [PATCH 069/337] Fixed warnings for java compilation --- .../registry/monitoring/blackbox/ProbingAction.java | 11 +++++------ .../registry/monitoring/blackbox/ProbingStep.java | 4 ++-- .../google/registry/monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/handlers/ActionHandler.java | 6 +++--- .../blackbox/handlers/WebWhoisActionHandler.java | 2 +- .../blackbox/messages/HttpRequestMessage.java | 3 ++- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 0265390fafe..c7645f29e6a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -67,8 +67,6 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -142,13 +140,14 @@ public ChannelFuture call() { timer.newTimeout(timeout -> { // Write appropriate outboundMessage to pipeline - channel().writeAndFlush(outboundMessage()); + ChannelFuture unusedFutureWriteAndFlush = + channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( future -> { if (future.isSuccess()) { - finished.setSuccess(); + ChannelFuture unusedFuture = finished.setSuccess(); } else { - finished.setFailure(future.cause()); + ChannelFuture unusedFuture = finished.setFailure(future.cause()); } }, //If we don't have a persistent connection, close the connection to this channel @@ -276,7 +275,7 @@ private static void addHandlers( @Override - public String toString() { + public final String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 3df536a9478..332a8d0de04 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -105,7 +105,7 @@ private ProbingAction generateAction(Token token) throws UndeterminedStateExcept /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { - return (isLastStep) ? token.next() : token; + return isLastStep ? token.next() : token; } /** @@ -167,7 +167,7 @@ public void accept(Token token) { } @Override - public String toString() { + public final String toString() { return String.format("ProbingStep with Protocol: %s\n" + "OutboundMessage: %s\n", protocol(), diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 92470ef62c8..b430d79507a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -58,7 +58,7 @@ public abstract static class Builder { } @Override - public String toString() { + public final String toString() { return String.format( "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", name(), diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 8f2319b3d39..6b6dad914a4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -65,7 +65,7 @@ public void handlerAdded(ChannelHandlerContext ctx) { public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - finished.setSuccess(); + ChannelFuture unusedFuture = finished.setSuccess(); } /** @@ -86,14 +86,14 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atInfo().log(cause.getMessage()); //As always, inform the ProbingStep that we successfully completed this action - finished.setFailure(cause); + ChannelFuture unusedFuture = finished.setFailure(cause); } else { //On UndeterminedStateException, we know the response type is an error. //Since it wasn't a success, we still log what caused the ERROR logger.atWarning().log(cause.getMessage()); - finished.setFailure(cause); + ChannelFuture unusedFuture = finished.setFailure(cause); //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 34eac2a0118..de20c6b9269 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -86,7 +86,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { + if (response.status().equals(HttpResponseStatus.OK)) { logger.atInfo().log("Received Successful HttpResponseStatus"); logger.atInfo().log("Response Received: " + response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 5e9300d0f34..8d285811e0d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,6 +19,7 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import java.util.Arrays; import javax.inject.Inject; /** @@ -69,7 +70,7 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx throw new IllegalArgumentException( String.format( "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + args, args.length)); + + " Received %d arguments instead of: " + Arrays.toString(args), args.length)); } } From 31057df4f9d284aaaec8dddb2448050abc489710 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 17:01:14 -0400 Subject: [PATCH 070/337] Fixed files to pass all style tests --- .../registry/monitoring/blackbox/Prober.java | 10 +- .../monitoring/blackbox/ProberModule.java | 32 ++++-- .../monitoring/blackbox/ProbingAction.java | 108 +++++++++++------- .../monitoring/blackbox/ProbingSequence.java | 39 ++++--- .../monitoring/blackbox/ProbingStep.java | 75 +++++++----- .../monitoring/blackbox/Protocol.java | 16 ++- .../monitoring/blackbox/WebWhoisModule.java | 80 +++++++++---- .../exceptions/ConnectionException.java | 4 +- .../UndeterminedStateException.java | 5 +- .../blackbox/handlers/ActionHandler.java | 48 +++++--- .../handlers/SslClientInitializer.java | 11 +- .../handlers/WebWhoisActionHandler.java | 53 ++++++--- .../handlers/WebWhoisMessageHandler.java | 21 ++-- .../blackbox/messages/HttpRequestMessage.java | 19 ++- .../messages/HttpResponseMessage.java | 6 +- .../blackbox/messages/InboundMessageType.java | 4 +- .../messages/OutboundMessageType.java | 10 +- .../monitoring/blackbox/tokens/Token.java | 41 ++++--- .../blackbox/tokens/WebWhoisToken.java | 36 ++++-- .../blackbox/ProbingActionTest.java | 17 ++- .../monitoring/blackbox/ProbingStepTest.java | 37 +++--- .../blackbox/TestServers/TestServer.java | 58 ---------- .../monitoring/blackbox/TestUtils.java | 32 ++++-- .../blackbox/handlers/ConversionHandler.java | 16 ++- .../blackbox/handlers/NettyRule.java | 37 +++--- .../handlers/SslClientInitializerTest.java | 36 +++--- .../blackbox/handlers/TestActionHandler.java | 4 +- .../handlers/WebWhoisActionHandlerTest.java | 18 +-- .../blackbox/testservers/TestServer.java | 68 +---------- .../WebWhoisServer.java | 50 +++++--- .../blackbox/tokens/WebWhoisTokenTest.java | 2 - 31 files changed, 563 insertions(+), 430 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java rename prober/src/test/java/google/registry/monitoring/blackbox/{TestServers => testservers}/WebWhoisServer.java (70%) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 5ca423c29cc..433d7361d5b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -18,12 +18,16 @@ import google.registry.monitoring.blackbox.ProberModule.ProberComponent; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by + * Dagger. */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + /** + * Main Dagger Component + */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() + .build(); public static void main(String[] args) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index f9db4865f78..df8b5fdbabd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -28,36 +28,50 @@ import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores - * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. + * Dagger main module, which {@link Provides} all objects that are shared between sequences and + * stores {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link + * ProbingSequence}. */ @Module public class ProberModule { - /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + /** + * Default {@link Duration} chosen to be time between each {@link ProbingAction} call. + */ private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ + /** + * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. + */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + /** + * {@link Provides} one global {@link Channel} class that is used to construct a {@link + * io.netty.bootstrap.Bootstrap}. + */ @Provides @Singleton Class provideChannelClazz() { return NioSocketChannel.class; } - /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ + + /** + * {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. + */ @Provides @Singleton Duration provideDuration() { return DEFAULT_DURATION; } - /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ + /** + * {@link Provides} the {@link SslProvider} used by instances of {@link + * google.registry.monitoring.blackbox.handlers.SslClientInitializer} + */ @Provides @Singleton static SslProvider provideSslProvider() { @@ -65,7 +79,9 @@ static SslProvider provideSslProvider() { return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - /** Root level {@link Component} that provides each {@link ProbingSequence}. */ + /** + * Root level {@link Component} that provides each {@link ProbingSequence}. + */ @Singleton @Component( modules = { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index c7645f29e6a..cdb099e4a76 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -26,40 +26,42 @@ import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; +import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; import javax.inject.Provider; +import org.joda.time.Duration; /** * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the - * task has been completed

+ * to perform its specified task, and return the {@link ChannelFuture} that will be informed when + * the task has been completed

* - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. - * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} - * gives the outline and {@link ProbingAction} gives the details of that connection.

+ *

Is an immutable class, as it is comprised of the tools necessary for making a specific type + * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall + * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the + * details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes + * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when + * informed that the connection is successful. If the channel is supplied, the connection future is + * automatically set to successful.

*/ @AutoValue @@ -67,32 +69,51 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** + * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when + * channel is active. + */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey + .valueOf("CONNECTION_FUTURE_KEY"); - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + /** + * {@link AttributeKey} in channel that gives the information of the channel's host. + */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey + .valueOf("REMOTE_ADDRESS_KEY"); - /** {@link Timer} that rate limits probing */ + /** + * {@link Timer} that rate limits probing + */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ + /** + * Actual {@link Duration} of this delay + */ public abstract Duration delay(); - /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ + /** + * {@link OutboundMessageType} instance that we write and flush down pipeline to server + */ public abstract OutboundMessageType outboundMessage(); - /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + /** + * {@link Channel} object that either created by or passed into this {@link ProbingAction} + * instance + */ @Nullable public abstract Channel channel(); - /** The {@link Protocol} instance that specifies type of connection */ + /** + * The {@link Protocol} instance that specifies type of connection + */ public abstract Protocol protocol(); - /** The hostname of the remote host we have a connection or will make a connection to */ + /** + * The hostname of the remote host we have a connection or will make a connection to + */ public abstract String host(); - /** * Performs the work of the actual action * @@ -111,7 +132,10 @@ public abstract class ProbingAction implements Callable { */ - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + /** + * Method that calls on {@code performAction} when it is certain channel connection is + * established. + */ @Override public ChannelFuture call() { //ChannelPromise that we return @@ -132,7 +156,8 @@ public ChannelFuture call() { try { actionHandler = channel().pipeline().get(ActionHandler.class); } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + //If we don't actually have an ActionHandler instance, we have an issue, and throw + // an UndeterminedStateException logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } @@ -150,7 +175,8 @@ public ChannelFuture call() { ChannelFuture unusedFuture = finished.setFailure(future.cause()); } }, - //If we don't have a persistent connection, close the connection to this channel + //If we don't have a persistent connection, close the connection to this + // channel future -> { if (!protocol().persistentConnection()) { @@ -163,7 +189,8 @@ public ChannelFuture call() { } else { logger.atWarning() .log( - "Could not close channel. Stale connection still exists."); + "Could not close channel. Stale connection still exists" + + "."); } } ); @@ -186,9 +213,12 @@ public ChannelFuture call() { } - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + /** + * {@link AutoValue.Builder} that does work of creating connection when not already present. + */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; public Builder setBootstrap(Bootstrap bootstrap) { @@ -223,7 +253,8 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); + checkArgument(channel() == null ^ bootstrap == null, + "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel @@ -273,14 +304,13 @@ private static void addHandlers( } - @Override public final String toString() { return String.format( - "ProbingAction with delay: %d\n" + - "outboundMessage: %s\n" + - "protocol: %s\n" + - "host: %s\n", + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 91c4165c068..175cf4dcfa5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -23,16 +23,21 @@ * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * * - *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

+ *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} + * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one + * is the first repeated step.

* - *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

+ *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once + * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest + * of the work.

*/ public class ProbingSequence { + private ProbingStep firstStep; - /**Each {@link ProbingSequence} requires a start token to begin running. */ + /** + * Each {@link ProbingSequence} requires a start token to begin running. + */ private Token startToken; public void start() { @@ -41,8 +46,8 @@ public void start() { } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link + * Bootstrap}. */ public static class Builder { @@ -57,33 +62,37 @@ public Builder(Token startToken) { } /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, - * built, and pointed to by the previous {@link ProbingStep} added. + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, built, and pointed to by + * the previous {@link ProbingStep} added. */ public Builder addStep(ProbingStep step) { - if (currentStep == null) + if (currentStep == null) { firstStep = step; - else + } else { currentStep.nextStep(step); + } currentStep = step; return this; } - /** We take special note of the first repeated step. */ + /** + * We take special note of the first repeated step. + */ public Builder markFirstRepeated() { firstRepeatedStep = currentStep; return this; } /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and - * calls private constructor to create {@link ProbingSequence}. + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private + * constructor to create {@link ProbingSequence}. */ public ProbingSequence build() { - if (firstRepeatedStep == null) + if (firstRepeatedStep == null) { firstRepeatedStep = firstStep; + } currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 332a8d0de04..98867c01220 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -17,47 +17,59 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import java.util.function.Consumer; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step - * in {@link ProbingSequence}. + * {@link AutoValue} class that represents generator of actions performed at each step in {@link + * ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. - * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, - * generates a new {@link ProbingAction} to call.

- * + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} + * instances. It then modifies these components on each loop iteration with the consumed {@link + * Token} and from that, generates a new {@link ProbingAction} to call.

*/ @AutoValue public abstract class ProbingStep implements Consumer { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Necessary boolean to inform when to obtain next {@link Token}*/ + /** + * Necessary boolean to inform when to obtain next {@link Token} + */ protected boolean isLastStep = false; private ProbingStep nextStep; - /** Time delay duration between actions. */ + /** + * Time delay duration between actions. + */ abstract Duration duration(); - /** {@link Protocol} type for this step. */ + /** + * {@link Protocol} type for this step. + */ abstract Protocol protocol(); - /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ + /** + * {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. + */ abstract OutboundMessageType messageTemplate(); - /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ + /** + * {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation + * of new channels. + */ abstract Bootstrap bootstrap(); + /** Default {@link AutoValue.Builder} for {@link ProbingStep}. */ @AutoValue.Builder - public static abstract class Builder { + public abstract static class Builder { + public abstract Builder setDuration(Duration value); public abstract Builder setProtocol(Protocol value); @@ -85,7 +97,9 @@ ProbingStep nextStep() { return this.nextStep; } - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ + /** + * Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} + */ private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() @@ -94,29 +108,33 @@ private ProbingAction generateAction(Token token) throws UndeterminedStateExcept .setOutboundMessage(message) .setHost(token.host()); - if (token.channel() != null) + if (token.channel() != null) { probingActionBuilder.setChannel(token.channel()); - else + } else { probingActionBuilder.setBootstrap(bootstrap()); + } return probingActionBuilder.build(); } - /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ + /** + * On the last step, gets the next {@link Token}. Otherwise, uses the same one. + */ private Token generateNextToken(Token token) { return isLastStep ? token.next() : token; } /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the + * action. * * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. * *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

+ * we note an error. Otherwise, if the future marked as finished when the action is completed is + * marked as a success, we note a success. Otherwise, if the cause of failure will either be a + * failure or error.

*/ @Override public void accept(Token token) { @@ -124,18 +142,17 @@ public void accept(Token token) { //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(UndeterminedStateException e) { + } catch (UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - ChannelFuture future; try { //call the generated action future = currentAction.call(); - } catch(Exception e) { + } catch (Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); @@ -144,7 +161,6 @@ public void accept(Token token) { return; } - future.addListener(f -> { if (f.isSuccess()) { //On a successful result, we log as a successful step, and not a success @@ -155,9 +171,10 @@ public void accept(Token token) { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - if (protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token + if (protocol().persistentConnection()) { + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + } //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); @@ -168,8 +185,8 @@ public void accept(Token token) { @Override public final String toString() { - return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n", + return String.format("ProbingStep with Protocol: %s\n" + + "OutboundMessage: %s\n", protocol(), messageTemplate().getClass().getName()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index b430d79507a..676fd80d740 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -26,23 +26,30 @@ @AutoValue public abstract class Protocol { - /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + /** + * {@link AttributeKey} that lets channel reference {@link Protocol} that created it. + */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); public abstract String name(); public abstract int port(); - /** The {@link ChannelHandler} providers to use for the protocol, in order. */ + /** + * The {@link ChannelHandler} providers to use for the protocol, in order. + */ abstract ImmutableList> handlerProviders(); - /** Boolean that notes if connection associated with Protocol is persistent.*/ + /** + * Boolean that notes if connection associated with Protocol is persistent. + */ abstract boolean persistentConnection(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } + /** Default {@link AutoValue.Builder} for {@link Protocol}. */ @AutoValue.Builder public abstract static class Builder { @@ -50,7 +57,8 @@ public abstract static class Builder { public abstract Builder setPort(int num); - public abstract Builder setHandlerProviders(ImmutableList> providers); + public abstract Builder setHandlerProviders( + ImmutableList> providers); public abstract Builder setPersistentConnection(boolean value); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index de041afad38..55fc7cf71a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -36,7 +36,9 @@ import javax.inject.Singleton; import org.joda.time.Duration; -/** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ +/** + * A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. + */ @Module public class WebWhoisModule { @@ -45,23 +47,39 @@ public class WebWhoisModule { private static final String HTTP_PROTOCOL_NAME = "http"; private static final String HTTPS_PROTOCOL_NAME = "https"; - /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + /** + * Standard length of messages used by Proxy. Equates to 0.5 MB. + */ private static final int maximumMessageLengthBytes = 512 * 1024; - /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ + /** + * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. + */ @Qualifier - public @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol { - /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ + } + + /** + * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. + */ @Qualifier - public @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol { + + } - /** Dagger qualifier to provide any WebWhois related bindings. */ + /** + * Dagger qualifier to provide any WebWhois related bindings. + */ @Qualifier - public @interface WebWhoisProtocol {} + public @interface WebWhoisProtocol { + + } - /** {@link Provides} standard WebWhois sequence. */ + /** + * {@link Provides} standard WebWhois sequence. + */ @Provides @Singleton @IntoSet @@ -75,7 +93,9 @@ ProbingSequence provideWebWhoisSequence( } - /** {@link Provides} only step used in WebWhois sequence. */ + /** + * {@link Provides} only step used in WebWhois sequence. + */ @Provides @WebWhoisProtocol static ProbingStep provideWebWhoisStep( @@ -92,7 +112,9 @@ static ProbingStep provideWebWhoisStep( .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ + /** + * {@link Provides} the {@link Protocol} that corresponds to http connection. + */ @Singleton @Provides @HttpWhoisProtocol @@ -107,7 +129,9 @@ static Protocol provideHttpWhoisProtocol( .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ + /** + * {@link Provides} the {@link Protocol} that corresponds to https connection. + */ @Singleton @Provides @HttpsWhoisProtocol @@ -123,7 +147,10 @@ static Protocol provideHttpsWhoisProtocol( } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ + /** + * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http + * protocol. + */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( @@ -138,11 +165,15 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ + /** + * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https + * protocol. + */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( - @HttpsWhoisProtocol Provider> sslClientInitializerProvider, + @HttpsWhoisProtocol + Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, Provider messageHandlerProvider, @@ -165,20 +196,25 @@ static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int ma return new HttpObjectAggregator(maxContentLength); } - /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + /** + * {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. + */ @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + static SslClientInitializer provideSslClientInitializer( + SslProvider sslProvider) { return new SslClientInitializer<>(sslProvider); } - /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + /** + * {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. + */ @Singleton @Provides @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClazz){ + Class channelClazz) { return new Bootstrap() .group(eventLoopGroup) .channel(channelClazz); @@ -190,12 +226,14 @@ int provideMaximumMessageLengthBytes() { return maximumMessageLengthBytes; } - /** {@link Provides} the list of top level domains to be probed */ + /** + * {@link Provides} the list of top level domains to be probed + */ @Singleton @Provides @WebWhoisProtocol ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); + return ImmutableList.of("how", "soy", "xn--q9jyb4c"); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index adb833ec629..776a231d6dd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,8 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when - * the action performed failed due to an issue in the connection with the server. + * Subclass of {@link UndeterminedStateException} that represents all instances when the action + * performed failed due to an issue in the connection with the server. */ public class ConnectionException extends UndeterminedStateException { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java index c155d695c7f..d7127717d52 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java @@ -15,9 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails - * before we can determine the state of the result, meaning the status - * is recorded as ERROR. + * Base exception class for all instances when the action performed fails before we can determine + * the state of the result, meaning the status is recorded as ERROR. */ public class UndeterminedStateException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 6b6dad914a4..6552bca3eca 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -16,28 +16,30 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; /** - *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline + * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType + * >}, as it should only be passed in messages that implement the {@link InboundMessageType} + * interface.

* - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error. If the error is an instance of a {@link FailureException} {@code finished} is - * marked as a failure with cause {@link FailureException}. If it is any other type of error, it - * is treated as an {@link UndeterminedStateException} and {@code finished} set as a failure with - * the same cause as what caused the exception. Lastly, if no error is thrown, we know the action - * completed as a success, and, as such, we mark {@code finished} as a success.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a + * {@link + * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this + * channel is informed of the error. If the error is an instance of a {@link FailureException} + * {@code finished} is marked as a failure with cause {@link FailureException}. If it is any other + * type of error, it is treated as an {@link UndeterminedStateException} and {@code finished} set as + * a failure with the same cause as what caused the exception. Lastly, if no error is thrown, we + * know the action completed as a success, and, as such, we mark {@code finished} as a success.

* *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ @@ -45,22 +47,30 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler privateKeySupplier, Supplier certificateSupplier) { + public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, + Supplier certificateSupplier) { //We use the default trust store here as well, setting trustCertificates to null this(sslProvider, null, privateKeySupplier, certificateSupplier); } @@ -99,8 +98,10 @@ protected void initChannel(C channel) throws Exception { SslContextBuilder.forClient() .sslProvider(sslProvider) .trustManager(trustedCertificates); - if (privateKeySupplier != null && certificateSupplier != null) - sslContextBuilder = sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get()); + if (privateKeySupplier != null && certificateSupplier != null) { + sslContextBuilder = sslContextBuilder + .keyManager(privateKeySupplier.get(), certificateSupplier.get()); + } SslHandler sslHandler = sslContextBuilder .build() diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index de20c6b9269..c0f7ce8ae78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,17 +14,15 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; @@ -38,10 +36,11 @@ import org.joda.time.Duration; /** - *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection - * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

+ *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response + * implies a redirection it follows the redirection until either an Error Response is received, or + * {@link HttpResponseStatus.OK} is received

*/ public class WebWhoisActionHandler extends ActionHandler { @@ -49,16 +48,24 @@ public class WebWhoisActionHandler extends ActionHandler { /** Dagger injected components necessary for redirect responses: */ - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + /** + * {@link Bootstrap} necessary for remaking connection on redirect response. + */ private final Bootstrap bootstrap; - /** {@link Protocol} for when redirected to http endpoint. */ + /** + * {@link Protocol} for when redirected to http endpoint. + */ private final Protocol httpWhoisProtocol; - /** {@link Protocol} for when redirected to https endpoint. */ + /** + * {@link Protocol} for when redirected to https endpoint. + */ private final Protocol httpsWhoisProtocol; - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + /** + * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. + */ private final HttpRequestMessage requestMessage; @Inject @@ -76,9 +83,10 @@ public WebWhoisActionHandler( /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, + * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a + * response indicating a Failure, or receives a redirection response, where it follows the + * redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) @@ -101,13 +109,17 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException( + "Redirected Location was invalid. Given Location was: " + response.headers() + .get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, url.getDefaultPort(), newPath)); + logger.atInfo().log(String + .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, + url.getDefaultPort(), newPath)); //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; @@ -116,7 +128,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new FailureException("Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); + throw new FailureException( + "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -141,10 +154,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atWarning().log("Channel was unsuccessfully closed."); } - //Once channel is closed, establish new connection to redirected host, and repeat same actions + //Once channel is closed, establish new connection to redirected host, and repeat + // same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + //Once we have a successful call, set original ChannelPromise as success to tell + // ProbingStep we can move on secondFuture.addListener(f2 -> { if (f2.isSuccess()) { super.channelRead0(ctx, msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 58c395ad86e..576d6a04d42 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -24,25 +24,32 @@ import javax.inject.Inject; /** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} - * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection. + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom + * type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for + * redirection. */ public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject - public WebWhoisMessageHandler() {} + public WebWhoisMessageHandler() { + } - /** Retains {@link HttpRequestMessage} and calls super write method. */ + /** + * Retains {@link HttpRequestMessage} and calls super write method. + */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) + throws Exception { HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ + /** + * Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link + * InboundMessageType} instance. + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8d285811e0d..92e43501438 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -26,8 +26,8 @@ * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. * *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

+ * that modifies the request to reflect the new host and optional path. We also implement a {@code + * name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { @@ -39,7 +39,9 @@ public HttpRequestMessage() { private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, + ByteBuf content) { super(httpVersion, method, uri, content); } @@ -50,19 +52,24 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ + /** + * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} + */ public HttpRequestMessage(FullHttpRequest request) { this(request.protocolVersion(), request.method(), request.uri(), request.content()); request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } - /** Modifies headers to reflect new host and new path if applicable. */ + /** + * Modifies headers to reflect new host and new path if applicable. + */ @Override public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { if (args.length == 1 || args.length == 2) { headers().set("host", args[0]); - if (args.length == 2) + if (args.length == 2) { setUri(args[1]); + } return this; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index f1b2d6ac6a7..7d2ff722076 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -29,8 +29,10 @@ private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, Byte super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { + /** + * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} + */ + public HttpResponseMessage(FullHttpResponse response) { this(response.protocolVersion(), response.status(), response.content()); response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 578526933ba..1d686e4ec34 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -17,4 +17,6 @@ /** * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ -public interface InboundMessageType {} +public interface InboundMessageType { + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 6e3da3f69d2..e435ae59f86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -21,10 +21,16 @@ */ public interface OutboundMessageType { - /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + /** + * All {@link OutboundMessageType} implementing classes should be able to be modified by token + * with String arguments + */ OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; - /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + /** + * Necessary to inform metrics collector what kind of message is sent down {@link + * io.netty.channel.ChannelPipeline} + */ @Override String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dab5851e8d8..b10c45dae8a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,19 +14,19 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.ProbingSequence; import google.registry.monitoring.blackbox.ProbingStep; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} - * in a single loop of a {@link ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} in a single loop of a + * {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes - * on channel that remains unchanged within a loop of the sequence.

+ * in a {@link ProbingSequence}. Additionally, passes on channel that remains unchanged within a + * loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop * in the sequence.

@@ -34,27 +34,38 @@ public abstract class Token { /** - * {@link Channel} that always starts out as null. Once a persistent connection - * is made (such as EPP), that channel is stored in the token and passed on to - * later steps in the sequence until a new loop begins. + * {@link Channel} that always starts out as null. Once a persistent connection is made (such as + * EPP), that channel is stored in the token and passed on to later steps in the sequence until a + * new loop begins. */ protected Channel channel; - /** Obtains next {@link Token} for next loop in sequence. */ + /** + * Obtains next {@link Token} for next loop in sequence. + */ public abstract Token next(); - /** String corresponding to host that is relevant for loop in sequence. */ + /** + * String corresponding to host that is relevant for loop in sequence. + */ public abstract String host(); - /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; + /** + * Modifies the {@link OutboundMessageType} in the manner necessary for each loop + */ + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) + throws UndeterminedStateException; - /** Set method for {@code channel} */ + /** + * Set method for {@code channel} + */ public void setChannel(Channel channel) { this.channel = channel; } - /** Get method for {@code channel}. */ + /** + * Get method for {@code channel}. + */ public Channel channel() { return this.channel; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index bb06ee89db6..3ff852f3556 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -19,26 +19,30 @@ import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import java.util.Iterator; -import java.util.LinkedList; import javax.inject.Inject; -import javax.inject.Named; /** * {@link Token} subtype designed for WebWhois sequence. * *

Between loops of a WebWhois sequence the only thing changing is the tld we - * are probing. As a result, we maintain the list of {@code topLevelDomains} and - * on each call to next, have our index looking at the next {@code topLevelDomain}.

+ * are probing. As a result, we maintain the list of {@code topLevelDomains} and on each call to + * next, have our index looking at the next {@code topLevelDomain}.

*/ public class WebWhoisToken extends Token { - /** For each top level domain (tld), we probe "prefix.tld". */ - private final static String PREFIX = "whois.nic."; + /** + * For each top level domain (tld), we probe "prefix.tld". + */ + private static final String PREFIX = "whois.nic."; - /** {@link ImmutableList} of all top level domains to be probed. */ + /** + * {@link ImmutableList} of all top level domains to be probed. + */ private final Iterator topLevelDomainsIterator; - /** Current index of {@code topLevelDomains} that represents tld we are probing. */ + /** + * Current index of {@code topLevelDomains} that represents tld we are probing. + */ private String currentDomain; @Inject @@ -48,20 +52,28 @@ public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { currentDomain = topLevelDomainsIterator.next(); } - /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ + /** + * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. + */ @Override public WebWhoisToken next() { currentDomain = topLevelDomainsIterator.next(); return this; } - /** Modifies message to reflect the new host coming from the new top level domain. */ + /** + * Modifies message to reflect the new host coming from the new top level domain. + */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + public OutboundMessageType modifyMessage(OutboundMessageType original) + throws UndeterminedStateException { return original.modifyMessage(host()); } - /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ + /** + * Returns host as the concatenation of fixed {@code prefix} and current value of {@code + * topLevelDomains}. + */ @Override public String host() { return PREFIX + currentDomain; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index f7857dd80f9..6cfb235d97c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -43,14 +43,16 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; + /** * Unit tests for {@link ProbingAction} subtypes * *

Attempts to test how well each {@link ProbingAction} works with an {@link ActionHandler} * subtype when receiving to all possible types of responses

- * */ + */ @RunWith(JUnit4.class) public class ProbingActionTest { + private static final String TEST_MESSAGE = "MESSAGE_TEST"; private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; @@ -59,14 +61,19 @@ public class ProbingActionTest { private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ + /** + * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on + * {@link ProbingAction} + */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); private Provider testHandlerProvider = () -> testHandler; private Provider conversionHandlerProvider = () -> conversionHandler; - /** Used for testing how well probing step can create connection to blackbox server */ + /** + * Used for testing how well probing step can create connection to blackbox server + */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); @@ -152,10 +159,10 @@ public void testSuccess_newChannel() throws Exception { //Tests to see if message is properly sent to remote server nettyRule.assertReceivedMessage(TEST_MESSAGE); - future.syncUninterruptibly(); + future = future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler) testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 1f09dd13553..307d19221dd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -48,29 +48,39 @@ import org.junit.Test; import org.mockito.Mockito; -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +/** + * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific + * implementations + */ public class ProbingStepTest { - /** Basic Constants necessary for tests */ - private final static String ADDRESS_NAME = "TEST_ADDRESS"; - private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final static int PROTOCOL_PORT = 0; - private final static String TEST_MESSAGE = "TEST_MESSAGE"; - private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + /** + * Basic Constants necessary for tests + */ + private static final String ADDRESS_NAME = "TEST_ADDRESS"; + private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private static final int PROTOCOL_PORT = 0; + private static final String TEST_MESSAGE = "TEST_MESSAGE"; + private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private static final LocalAddress ADDRESS = new LocalAddress(ADDRESS_NAME); private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); - /** Used for testing how well probing step can create connection to blackbox server */ + /** + * Used for testing how well probing step can create connection to blackbox server + */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + /** + * The two main handlers we need in any test pipeline used that connects to {@link NettyRule's + * server} + **/ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); @@ -119,7 +129,7 @@ public void testNewChannel() throws Exception { Token testToken = new NewChannelToken(ADDRESS_NAME); //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(address); + nettyRule.setUpServer(ADDRESS); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -179,7 +189,8 @@ public void testWithSequence_ExistingChannel() throws Exception { assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + //Call accept on the first step, which should send our message through the EmbeddedChannel + // pipeline firstStep.accept(testToken); Object msg = channel.readOutbound(); @@ -188,7 +199,7 @@ public void testWithSequence_ExistingChannel() throws Exception { msg = channel.readOutbound(); } //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + assertThat(((ByteBuf) channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java deleted file mode 100644 index 46615a506fb..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; - -import com.google.common.collect.ImmutableList; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; -import io.netty.channel.nio.NioEventLoopGroup; - -/** - * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform - */ -public abstract class TestServer { - - TestServer(LocalAddress localAddress, ImmutableList handlers) { - this(new NioEventLoopGroup(1), localAddress, handlers); - } - - TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - //Creates ChannelInitializer with handlers specified - ChannelInitializer serverInitializer = new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) { - for (ChannelHandler handler : handlers) { - ch.pipeline().addLast(handler); - } - } - }; - //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using LocalServerChannel class - ServerBootstrap serverBootstrap = - new ServerBootstrap() - .group(eventLoopGroup) - .channel(LocalServerChannel.class) - .childHandler(serverInitializer); - - ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 50c60d9fc52..c0c5831a68c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -29,7 +29,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** Utility class for various helper methods used in testing. */ +/** + * Utility class for various helper methods used in testing. + */ public class TestUtils { public static FullHttpRequest makeHttpGetRequest(String host, String path) { @@ -52,7 +54,9 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { return response; } - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + /** + * Creates HttpResponse given status, redirection location, and other necessary inputs + */ public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); @@ -66,13 +70,17 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** Basic outline for {@link Token} instances to be used in tests */ - static abstract class TestToken extends Token { + /** + * Basic outline for {@link Token} instances to be used in tests + */ + abstract static class TestToken extends Token { + protected String host; protected TestToken(String host) { this.host = host; } + @Override public Token next() { return this; @@ -90,29 +98,29 @@ public String host() { } - /** {@link TestToken} instance that creates new channel */ + /** + * {@link TestToken} instance that creates new channel + */ public static class NewChannelToken extends TestToken { + public NewChannelToken(String host) { super(host); } + @Override public Channel channel() { return null; } } - /** {@link TestToken} instance that passes in existing channel */ + /** + * {@link TestToken} instance that passes in existing channel + */ public static class ExistingChannelToken extends TestToken { - private Channel channel; - public ExistingChannelToken(Channel channel, String host) { super(host); this.channel = channel; } - @Override - public Channel channel() { - return channel; - } } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index c9d337d6ad8..987abbfd7dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -28,15 +28,17 @@ import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to - * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link + * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} + * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** Handles inbound conversion */ + /** + * Handles inbound conversion + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; @@ -44,7 +46,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception buf.release(); } - /** Handles outbound conversion */ + /** + * Handles outbound conversion + */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 86b54d9a07d..f51f8c8fd61 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -28,7 +28,7 @@ import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -52,23 +52,24 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest} + *

*/ public final class NettyRule extends ExternalResource { - // All I/O operations are done inside the single thread within this event loop group, which is // different from the main test thread. Therefore synchronizations are required to make sure that // certain I/O activities are finished when assertions are performed. public NettyRule() { eventLoopGroup = new NioEventLoopGroup(1); } + public NettyRule(EventLoopGroup e) { eventLoopGroup = e; } + private final EventLoopGroup eventLoopGroup; - private WebWhoisServer webWhoisServer; // Handler attached to server's channel to record the request received. private EchoHandler echoHandler; @@ -78,16 +79,20 @@ public NettyRule(EventLoopGroup e) { private Channel channel; - /** Sets up a server channel bound to the given local address. */ + /** + * Sets up a server channel bound to the given local address. + */ public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.builder().add(handlers).add(echoHandler).build()); } - /** Sets up a client channel connecting to the give local address. */ + /** + * Sets up a client channel connecting to the give local address. + */ void setUpClient( LocalAddress localAddress, Protocol protocol, @@ -121,7 +126,9 @@ private void checkReady() { checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); } - /** Test that custom setup to send message to current server sends right message */ + /** + * Test that custom setup to send message to current server sends right message + */ public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); @@ -130,9 +137,9 @@ public void assertReceivedMessage(String message) throws Exception { /** * Test that a message can go through, both inbound and outbound. * - *

The client writes the message to the server, which echos it back and saves the string in its - * promise. The client receives the echo and saves it in its promise. All these activities happens - * in the I/O thread, and this call itself returns immediately. + *

The client writes the message to the server, which echos it back and saves the string in + * its promise. The client receives the echo and saves it in its promise. All these activities + * happens in the I/O thread, and this call itself returns immediately. */ void assertThatMessagesWork() throws Exception { checkReady(); @@ -196,7 +203,9 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E } } - /** A handler that dumps its inbound message to a promise that can be inspected later. */ + /** + * A handler that dumps its inbound message to a promise that can be inspected later. + */ private static class DumpHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture responseFuture = new CompletableFuture<>(); @@ -217,7 +226,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception responseFuture.complete(response); } - /** Saves any inbound error into the failure cause of the promise. */ + /** + * Saves any inbound error into the failure cause of the promise. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 523fb228752..25e5608a100 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -62,10 +62,14 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - /** Fake host to test if the SSL engine gets the correct peer host. */ + /** + * Fake host to test if the SSL engine gets the correct peer host. + */ private static final String SSL_HOST = "www.example.tld"; - /** Fake port to test if the SSL engine gets the correct peer port. */ + /** + * Fake port to test if the SSL engine gets the correct peer port. + */ private static final int SSL_PORT = 12345; @Rule @@ -78,20 +82,24 @@ public class SslClientInitializerTest { @Parameters(name = "{0}") public static SslProvider[] data() { return OpenSsl.isAvailable() - ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[] {SslProvider.JDK}; + ? new SslProvider[]{SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[]{SslProvider.JDK}; } - /** Saves the SNI hostname received by the server, if sent by the client. */ + /** + * Saves the SNI hostname received by the server, if sent by the client. + */ private String sniHostReceived; - /** Fake protocol saved in channel attribute. */ - private final static Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + /** + * Fake protocol saved in channel attribute. + */ + private static final Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -166,7 +174,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); @@ -195,7 +203,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 95b06e623d1..19e608c97d2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -20,8 +20,8 @@ import io.netty.channel.ChannelHandlerContext; /** - * Concrete implementation of {@link ActionHandler} that does nothing different from - * parent class other than store and return the {@code inboundMessage} + * Concrete implementation of {@link ActionHandler} that does nothing different from parent class + * other than store and return the {@code inboundMessage} */ public class TestActionHandler extends ActionHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 33eb190a66a..5a0d0908724 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -17,17 +17,16 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; @@ -39,7 +38,6 @@ import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -54,15 +52,10 @@ public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; - private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; - private static final String HTTPS_REDIRECT = "https://"; - private static final String REDIRECT_HOST = "www.example.com"; - private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private static final Duration DEFAULT_DURATION = new Duration(0L); - private final Protocol STANDARD_PROTOCOL = Protocol.builder() + private final Protocol standardProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( null, null, null, null))) .setName("http") @@ -96,8 +89,8 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, - STANDARD_PROTOCOL, - STANDARD_PROTOCOL, + standardProtocol, + standardProtocol, messageTemplate ); actionHandlerProvider = () -> actionHandler; @@ -177,6 +170,7 @@ public void testBasic_responseFailure_badRequest() { assertThat(future.cause() instanceof FailureException).isTrue(); } + @SuppressWarnings("CheckReturnValue") @Test public void testBasic_responseFailure_badURL() { //setup diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java index c39fe554390..744dab17f5e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java @@ -14,38 +14,28 @@ package google.registry.monitoring.blackbox.testservers; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; - import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandler.Sharable; -import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to * perform */ -public class TestServer { +public abstract class TestServer { - public TestServer(LocalAddress localAddress, ImmutableList handlers) { + TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } - public TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, + TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @@ -68,56 +58,4 @@ protected void initChannel(LocalChannel ch) { } - public static TestServer webWhoisServer(EventLoopGroup eventLoopGroup, - LocalAddress localAddress, String redirectInput, String destinationInput, - String destinationPath) { - return new TestServer( - eventLoopGroup, - localAddress, - ImmutableList.of(new RedirectHandler(redirectInput, destinationInput, destinationPath)) - ); - } - - /** - * Handler that will wither redirect client, give successful response, or give error messge - */ - @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { - - private String redirectInput; - private String destinationInput; - private String destinationPath; - - /** - * @param redirectInput - Server will send back redirect to {@code destinationInput} when - * receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response - * when receiving a request with this host location - */ - public RedirectHandler(String redirectInput, String destinationInput, String destinationPath) { - this.redirectInput = redirectInput; - this.destinationInput = destinationInput; - this.destinationPath = destinationPath; - } - - /** - * Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on - * what header location is - */ - @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { - HttpResponse response; - if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true)); - } else if (request.headers().get("host").equals(destinationInput) - && request.uri().equals(destinationPath)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); - } - ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response); - - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java similarity index 70% rename from prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java rename to prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java index 28b36190a7e..d15a8a8e3a4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.TestServers; +package google.registry.monitoring.blackbox.testservers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; @@ -36,30 +37,40 @@ * {@link TestServer} subtype that performs WebWhois Services Expected * *

It will either redirect the client to the correct location if given the - * requisite redirect input, give the client a successful response if they give - * the expected final destination, or give the client an error message if given - * an unexpected host location

+ * requisite redirect input, give the client a successful response if they give the expected final + * destination, or give the client an error message if given an unexpected host location

*/ public class WebWhoisServer extends TestServer { - public WebWhoisServer(LocalAddress localAddress, ImmutableList handlers) { + public WebWhoisServer(LocalAddress localAddress, + ImmutableList handlers) { super(localAddress, handlers); } - public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, + ImmutableList handlers) { super(eventLoopGroup, localAddress, handlers); } - /** Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the HttpRequestMessage object through pipeline */ - public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + /** + * Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the + * HttpRequestMessage object through pipeline + */ + public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, + LocalAddress localAddress, String redirectInput, String destinationInput) { return new WebWhoisServer( eventLoopGroup, localAddress, ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) ); } - /** Creates server that sends exactly what we expect a remote server to send as a response, by sending the {@link ByteBuf} of the response through pipeline */ - public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + + /** + * Creates server that sends exactly what we expect a remote server to send as a response, by + * sending the {@link ByteBuf} of the response through pipeline + */ + public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, + String redirectInput, String destinationInput) { return new WebWhoisServer( eventLoopGroup, localAddress, @@ -75,31 +86,38 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr */ @Sharable static class RedirectHandler extends SimpleChannelInboundHandler { + private String redirectInput; private String destinationInput; /** - * - * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location + * @param redirectInput - Server will send back redirect to {@code destinationInput} when + * receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response + * when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; this.destinationInput = destinationInput; } - /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ + /** + * Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on + * what header location is + */ @Override public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, + false)); } else if (request.headers().get("host").equals(destinationInput)) { response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } - ctx.channel().writeAndFlush(response); + ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index bf5cfc45652..9a3e755364b 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -19,8 +19,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; From 28220e9e1e00e83fefbad5145e3e21c4595d0dae Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 20 Jun 2019 16:41:30 -0400 Subject: [PATCH 071/337] Initial Commit. --- .../monitoring/blackbox/ActionHandler.java | 5 + .../monitoring/blackbox/ProbingAction.java | 5 + .../monitoring/blackbox/ProbingSequence.java | 5 + .../monitoring/blackbox/ProbingStep.java | 5 + .../monitoring/blackbox/Protocol.java | 5 + .../monitoring/blackbox/TestToken.java | 5 + .../registry/monitoring/blackbox/Token.java | 5 + prober/build.gradle | 30 +- .../blackbox/AutoValue_NewChannelAction.java | 181 +++++++++++ .../blackbox/AutoValue_ProbingAction.java | 118 ++++++++ .../blackbox/AutoValue_Protocol.java | 153 ++++++++++ .../monitoring/blackbox/ActionHandler.java | 52 ++++ .../registry/monitoring/blackbox/Main.java | 8 + .../monitoring/blackbox/NewChannelAction.java | 70 +++++ .../monitoring/blackbox/ProbingAction.java | 285 ++++-------------- .../monitoring/blackbox/ProbingFlows.java | 15 + .../monitoring/blackbox/ProbingSequence.java | 86 +----- .../monitoring/blackbox/ProbingStep.java | 203 +++---------- .../monitoring/blackbox/Protocol.java | 59 ++-- .../monitoring/blackbox/TestToken.java | 28 ++ .../registry/monitoring/blackbox/Token.java | 20 ++ .../monitoring/blackbox/package-info.java | 16 + 22 files changed, 827 insertions(+), 532 deletions(-) create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Main.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/package-info.java diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java new file mode 100644 index 00000000000..a4d36657721 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ActionHandler { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java new file mode 100644 index 00000000000..6b26913d425 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingAction { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java new file mode 100644 index 00000000000..9f3617135a4 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingSequence { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java new file mode 100644 index 00000000000..b8b237a1e91 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingStep { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java new file mode 100644 index 00000000000..75d13b3039a --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class Protocol { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java new file mode 100644 index 00000000000..98f21f8d63a --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class TestToken { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java new file mode 100644 index 00000000000..16f05be0430 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class Token { + +} diff --git a/prober/build.gradle b/prober/build.gradle index 3652390d0ba..33feefb7175 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,30 +1,25 @@ -// Copyright 2019 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. - apply plugin: 'java' -createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') +createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Main') + dependencies { def deps = rootProject.dependencyMap + compile deps['com.beust:jcommander'] + compile deps['com.google.api-client:google-api-client'] + compile deps['com.google.apis:google-api-services-cloudkms'] + compile deps['com.google.apis:google-api-services-monitoring'] + compile deps['com.google.apis:google-api-services-storage'] compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] + compile deps['com.google.http-client:google-http-client'] + compile deps['com.google.monitoring-client:metrics'] + compile deps['com.google.monitoring-client:stackdriver'] compile deps['io.netty:netty-buffer'] compile deps['io.netty:netty-codec-http'] compile deps['io.netty:netty-codec'] @@ -41,10 +36,13 @@ dependencies { runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] + testCompile deps['com.google.monitoring-client:contrib'] testCompile deps['com.google.truth:truth'] + testCompile deps['org.yaml:snakeyaml'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') + testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -52,4 +50,4 @@ dependencies { testAnnotationProcessor deps['com.google.auto.value:auto-value'] annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] -} +} \ No newline at end of file diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java new file mode 100644 index 00000000000..6f818f03a28 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java @@ -0,0 +1,181 @@ + + +package google.registry.monitoring.blackbox; + +import io.netty.bootstrap.Bootstrap; +import javax.annotation.Generated; +import org.joda.time.Duration; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_NewChannelAction extends NewChannelAction { + + private final Duration delay; + + private final O outboundMessage; + + private final Protocol protocol; + + private final ActionHandler actionHandler; + + private final Bootstrap bootstrap; + + private AutoValue_NewChannelAction( + Duration delay, + O outboundMessage, + Protocol protocol, + ActionHandler actionHandler, + Bootstrap bootstrap) { + this.delay = delay; + this.outboundMessage = outboundMessage; + this.protocol = protocol; + this.actionHandler = actionHandler; + this.bootstrap = bootstrap; + } + + @Override + Duration delay() { + return delay; + } + + @Override + O outboundMessage() { + return outboundMessage; + } + + @Override + Protocol protocol() { + return protocol; + } + + @Override + ActionHandler actionHandler() { + return actionHandler; + } + + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + @Override + public String toString() { + return "NewChannelAction{" + + "delay=" + delay + ", " + + "outboundMessage=" + outboundMessage + ", " + + "protocol=" + protocol + ", " + + "actionHandler=" + actionHandler + ", " + + "bootstrap=" + bootstrap + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof NewChannelAction) { + NewChannelAction that = (NewChannelAction) o; + return this.delay.equals(that.delay()) + && this.outboundMessage.equals(that.outboundMessage()) + && this.protocol.equals(that.protocol()) + && this.actionHandler.equals(that.actionHandler()) + && this.bootstrap.equals(that.bootstrap()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= delay.hashCode(); + h$ *= 1000003; + h$ ^= outboundMessage.hashCode(); + h$ *= 1000003; + h$ ^= protocol.hashCode(); + h$ *= 1000003; + h$ ^= actionHandler.hashCode(); + h$ *= 1000003; + h$ ^= bootstrap.hashCode(); + return h$; + } + + static final class Builder extends NewChannelAction.Builder { + private Duration delay; + private O outboundMessage; + private Protocol protocol; + private ActionHandler actionHandler; + private Bootstrap bootstrap; + Builder() { + } + @Override + public NewChannelAction.Builder delay(Duration delay) { + if (delay == null) { + throw new NullPointerException("Null delay"); + } + this.delay = delay; + return this; + } + @Override + public NewChannelAction.Builder outboundMessage(O outboundMessage) { + if (outboundMessage == null) { + throw new NullPointerException("Null outboundMessage"); + } + this.outboundMessage = outboundMessage; + return this; + } + @Override + public NewChannelAction.Builder protocol(Protocol protocol) { + if (protocol == null) { + throw new NullPointerException("Null protocol"); + } + this.protocol = protocol; + return this; + } + @Override + public NewChannelAction.Builder actionHandler(ActionHandler actionHandler) { + if (actionHandler == null) { + throw new NullPointerException("Null actionHandler"); + } + this.actionHandler = actionHandler; + return this; + } + @Override + public NewChannelAction.Builder bootstrap(Bootstrap bootstrap) { + if (bootstrap == null) { + throw new NullPointerException("Null bootstrap"); + } + this.bootstrap = bootstrap; + return this; + } + @Override + public NewChannelAction build() { + String missing = ""; + if (this.delay == null) { + missing += " delay"; + } + if (this.outboundMessage == null) { + missing += " outboundMessage"; + } + if (this.protocol == null) { + missing += " protocol"; + } + if (this.actionHandler == null) { + missing += " actionHandler"; + } + if (this.bootstrap == null) { + missing += " bootstrap"; + } + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing required properties:" + missing); + } + return new AutoValue_NewChannelAction( + this.delay, + this.outboundMessage, + this.protocol, + this.actionHandler, + this.bootstrap); + } + } + +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java new file mode 100644 index 00000000000..26f560b145b --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java @@ -0,0 +1,118 @@ + + +package google.registry.monitoring.blackbox; + +import io.netty.channel.Channel; +import javax.annotation.Generated; +import org.joda.time.Duration; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_ProbingAction extends ProbingAction { + + private final Duration delay; + + private final O outboundMessage; + + private final Channel channel; + + private final Protocol protocol; + + private final ActionHandler actionHandler; + + AutoValue_ProbingAction( + Duration delay, + O outboundMessage, + Channel channel, + Protocol protocol, + ActionHandler actionHandler) { + if (delay == null) { + throw new NullPointerException("Null delay"); + } + this.delay = delay; + if (outboundMessage == null) { + throw new NullPointerException("Null outboundMessage"); + } + this.outboundMessage = outboundMessage; + if (channel == null) { + throw new NullPointerException("Null channel"); + } + this.channel = channel; + if (protocol == null) { + throw new NullPointerException("Null protocol"); + } + this.protocol = protocol; + if (actionHandler == null) { + throw new NullPointerException("Null actionHandler"); + } + this.actionHandler = actionHandler; + } + + @Override + Duration delay() { + return delay; + } + + @Override + O outboundMessage() { + return outboundMessage; + } + + @Override + Channel channel() { + return channel; + } + + @Override + Protocol protocol() { + return protocol; + } + + @Override + ActionHandler actionHandler() { + return actionHandler; + } + + @Override + public String toString() { + return "ProbingAction{" + + "delay=" + delay + ", " + + "outboundMessage=" + outboundMessage + ", " + + "channel=" + channel + ", " + + "protocol=" + protocol + ", " + + "actionHandler=" + actionHandler + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof ProbingAction) { + ProbingAction that = (ProbingAction) o; + return this.delay.equals(that.delay()) + && this.outboundMessage.equals(that.outboundMessage()) + && this.channel.equals(that.channel()) + && this.protocol.equals(that.protocol()) + && this.actionHandler.equals(that.actionHandler()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= delay.hashCode(); + h$ *= 1000003; + h$ ^= outboundMessage.hashCode(); + h$ *= 1000003; + h$ ^= channel.hashCode(); + h$ *= 1000003; + h$ ^= protocol.hashCode(); + h$ *= 1000003; + h$ ^= actionHandler.hashCode(); + return h$; + } + +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java new file mode 100644 index 00000000000..3247cbdd310 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java @@ -0,0 +1,153 @@ + + +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_Protocol extends Protocol { + + private final String name; + + private final int port; + + private final String host; + + private final ImmutableList> handlerProviders; + + private AutoValue_Protocol( + String name, + int port, + String host, + ImmutableList> handlerProviders) { + this.name = name; + this.port = port; + this.host = host; + this.handlerProviders = handlerProviders; + } + + @Override + String name() { + return name; + } + + @Override + int port() { + return port; + } + + @Override + String host() { + return host; + } + + @Override + ImmutableList> handlerProviders() { + return handlerProviders; + } + + @Override + public String toString() { + return "Protocol{" + + "name=" + name + ", " + + "port=" + port + ", " + + "host=" + host + ", " + + "handlerProviders=" + handlerProviders + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Protocol) { + Protocol that = (Protocol) o; + return this.name.equals(that.name()) + && this.port == that.port() + && this.host.equals(that.host()) + && this.handlerProviders.equals(that.handlerProviders()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= name.hashCode(); + h$ *= 1000003; + h$ ^= port; + h$ *= 1000003; + h$ ^= host.hashCode(); + h$ *= 1000003; + h$ ^= handlerProviders.hashCode(); + return h$; + } + + static final class Builder extends Protocol.Builder { + private String name; + private Integer port; + private String host; + private ImmutableList> handlerProviders; + Builder() { + } + @Override + Protocol.Builder name(String name) { + if (name == null) { + throw new NullPointerException("Null name"); + } + this.name = name; + return this; + } + @Override + Protocol.Builder port(int port) { + this.port = port; + return this; + } + @Override + Protocol.Builder host(String host) { + if (host == null) { + throw new NullPointerException("Null host"); + } + this.host = host; + return this; + } + @Override + Protocol.Builder handlerProviders(ImmutableList> handlerProviders) { + if (handlerProviders == null) { + throw new NullPointerException("Null handlerProviders"); + } + this.handlerProviders = handlerProviders; + return this; + } + @Override + Protocol build() { + String missing = ""; + if (this.name == null) { + missing += " name"; + } + if (this.port == null) { + missing += " port"; + } + if (this.host == null) { + missing += " host"; + } + if (this.handlerProviders == null) { + missing += " handlerProviders"; + } + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing required properties:" + missing); + } + return new AutoValue_Protocol( + this.name, + this.port, + this.host, + this.handlerProviders); + } + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java new file mode 100644 index 00000000000..1437d600539 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -0,0 +1,52 @@ +// 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.monitoring.blackbox; + +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import java.util.function.Function; + +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { + + private ChannelPromise finished; + private Channel channel; + + @Override + public ChannelFuture apply(O outboundMessage) { + // Send the request to server. + channel.writeAndFlush(outboundMessage); + return finished; + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) { + channel = ctx.channel(); + finished = ctx.newPromise(); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, I InboundMessage) { + // Response received, validate it, register metrics, etc. + // Once everything is done, mark the promise as success; + + finished.setSuccess(); + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java new file mode 100644 index 00000000000..61699ce033c --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java @@ -0,0 +1,8 @@ +package google.registry.monitoring.blackbox; + +public class Main { + public static void main(String[] args) { + System.out.println("Hello, world!"); + + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..ce452e19bf0 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,70 @@ +package google.registry.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOutboundInvoker; +import io.netty.channel.ChannelPromise; +import io.netty.channel.DefaultChannelPromise; +import io.netty.channel.socket.nio.NioSocketChannel; +import org.joda.time.Duration; + +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + abstract Bootstrap bootstrap(); + + private Channel channel; + + @Override + public Channel channel() { + return this.channel; + } + + @Override + public ChannelFuture call() { + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(NioSocketChannel outboundChannel) + throws Exception { + addHandlers( + outboundChannel.pipeline(), protocol().handlerProviders()); + } + }); + + ChannelFuture connectionFuture = bootstrap.connect(protocol().host(), protocol().port()); + ChannelPromise finished = null; + + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + this.channel = channelFuture.channel(); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + + } + } + ); + return finished; + } + + public static ProbingAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder(); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder outboundMessage(O value); + + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index cdb099e4a76..2ccf818a57a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,288 +14,104 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; -import io.netty.util.AttributeKey; import io.netty.util.HashedWheelTimer; import io.netty.util.Timer; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import javax.inject.Provider; -import org.joda.time.Duration; /** - * AutoValue class that represents action generated by {@link ProbingStep} + *Class that represents given action in sequence of probing * - *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when - * the task has been completed

- * - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type - * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall - * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the - * details of that connection.

- * - *

In its build, if there is no channel supplied, it will create a channel from the attributes - * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when - * informed that the connection is successful. If the channel is supplied, the connection future is - * automatically set to successful.

*/ -@AutoValue -public abstract class ProbingAction implements Callable { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** - * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when - * channel is active. - */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey - .valueOf("CONNECTION_FUTURE_KEY"); +public abstract class ProbingAction implements Callable { /** - * {@link AttributeKey} in channel that gives the information of the channel's host. - */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey - .valueOf("REMOTE_ADDRESS_KEY"); - - /** - * {@link Timer} that rate limits probing + * timer that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); /** - * Actual {@link Duration} of this delay + * @return actual Duration of delay */ - public abstract Duration delay(); + abstract Duration delay(); /** - * {@link OutboundMessageType} instance that we write and flush down pipeline to server + * @return message to send to server */ - public abstract OutboundMessageType outboundMessage(); + abstract O outboundMessage(); /** - * {@link Channel} object that either created by or passed into this {@link ProbingAction} - * instance + * @return Channel object that represents connection between prober client and server */ - @Nullable - public abstract Channel channel(); + abstract Channel channel(); /** - * The {@link Protocol} instance that specifies type of connection + * @return The Protocol instance that represents action to be tested by this part in sequences */ - public abstract Protocol protocol(); + abstract Protocol protocol(); /** - * The hostname of the remote host we have a connection or will make a connection to + * @return The requisite instance of Action Handler, which is always the last Handler in the pipeline */ - public abstract String host(); + abstract Bootstrap bootstrap(); + abstract ActionHandler actionHandler(); /** - * Performs the work of the actual action - * - *

First, checks if channel is active by setting a listener to perform the bulk of the work - * when the connection future is successful.

- * - *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

* - *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

- * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. + * @return Builder for the ProbingAction Class */ - /** - * Method that calls on {@code performAction} when it is certain channel connection is - * established. + * The method that calls the ActionHandler to send a message down the channel pipeline + * @return future that denotes when the action has been successfully performed */ @Override public ChannelFuture call() { - //ChannelPromise that we return - ChannelPromise finished = channel().newPromise(); - - //Ensures channel has been set up with connection future as an attribute - checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); - - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture connectionFuture) -> { - if (connectionFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - - ActionHandler actionHandler; - try { - actionHandler = channel().pipeline().get(ActionHandler.class); - } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw - // an UndeterminedStateException - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); - - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture unusedFutureWriteAndFlush = - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> { - if (future.isSuccess()) { - ChannelFuture unusedFuture = finished.setSuccess(); - } else { - ChannelFuture unusedFuture = finished.setFailure(future.cause()); - } - }, - //If we don't have a persistent connection, close the connection to this - // channel - future -> { - if (!protocol().persistentConnection()) { + // Add the Handlers from the run the action + // (with delay if present), and remove the ActionHandler afterwards, + // in case the channel is to be reused later. - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) { - logger.atInfo() - .log("Closed stale channel. Moving on to next ProbingStep"); - } else { - logger.atWarning() - .log( - "Could not close channel. Stale connection still exists" - + "."); - } - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(connectionFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); + ChannelPromise finished = channel().newPromise(); + timer.newTimeout(timeout -> + // Retry logic may also be added here. + actionHandler().apply(outboundMessage()).addListeners( + future -> finished.setSuccess()), + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } + abstract static class Builder, P extends ProbingAction> { - /** - * {@link AutoValue.Builder} that does work of creating connection when not already present. - */ - @AutoValue.Builder - public abstract static class Builder { - - private Bootstrap bootstrap; - - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } - - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setHost(String value); - - public abstract Builder setChannel(Channel channel); - - abstract Protocol protocol(); - - abstract Channel channel(); + public abstract B delay(Duration value); - abstract String host(); + public abstract B outboundMessage(O value); - abstract ProbingAction autoBuild(); + public abstract B protocol(Protocol value); - public ProbingAction build() { - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - address = new LocalAddress(host()); - } - - checkArgument(channel() == null ^ bootstrap == null, - "One and only one of bootstrap and channel must be supplied."); - //If a channel is supplied, nothing is needed to be done - - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel() == null) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); - - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } - - //now we can actually build the ProbingAction - return autoBuild(); - } - } + public abstract B actionHandler(ActionHandler value); - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); + public abstract P build(); } - /** - * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified - * * @param channelPipeline is pipeline associated with channel that we want to add handlers to * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - private static void addHandlers( + static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { @@ -304,17 +120,20 @@ private static void addHandlers( } - @Override - public final String toString() { - return String.format( - "ProbingAction with delay: %d\n" - + "outboundMessage: %s\n" - + "protocol: %s\n" - + "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); + + /** + * @param channelPipeline is pipeline associated with channel we want to remove handlers from + * removes all handlers from pipeline + */ + static void removeHandlers(ChannelPipeline channelPipeline) { + while (channelPipeline.first() != null) { + channelPipeline.removeFirst(); + } } + + + + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java new file mode 100644 index 00000000000..73dfd778d69 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox; + +public class ProbingFlows { + + public static void main(String[] args) { + ProbingSequence sequence = new ProbingSequence + .Builder() + .addStep(new ProbingStep()) + .build(); + + sequence.start(); + + + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 175cf4dcfa5..7c14d9f0bf0 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -1,72 +1,22 @@ -// Copyright 2019 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.monitoring.blackbox; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.EventLoopGroup; - -/** - * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. - * - * - *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} - * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one - * is the first repeated step.

- * - *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once - * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest - * of the work.

- */ -public class ProbingSequence { - +class ProbingSequence { private ProbingStep firstStep; - /** - * Each {@link ProbingSequence} requires a start token to begin running. - */ - private Token startToken; - public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + // create a new unique token; + Token token = new TestToken<>(); + firstStep.accept(token); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link - * Bootstrap}. + * Builder that sequentially adds steps */ - public static class Builder { - + static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - - private Token startToken; - public Builder(Token startToken) { - this.startToken = startToken; - } - - /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, built, and pointed to by - * the previous {@link ProbingStep} added. - */ public Builder addStep(ProbingStep step) { - if (currentStep == null) { firstStep = step; } else { @@ -75,34 +25,18 @@ public Builder addStep(ProbingStep step) { currentStep = step; return this; - } - /** - * We take special note of the first repeated step. - */ - public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; - return this; } - /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private - * constructor to create {@link ProbingSequence}. - */ public ProbingSequence build() { - if (firstRepeatedStep == null) { - firstRepeatedStep = firstStep; - } - - currentStep.nextStep(firstRepeatedStep); - currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + currentStep.nextStep(firstStep); + return new ProbingSequence(this.firstStep); } + } - private ProbingSequence(ProbingStep firstStep, Token startToken) { + private ProbingSequence(ProbingStep firstStep) { this.firstStep = firstStep; - this.startToken = startToken; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 98867c01220..2e2e3575d07 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -1,196 +1,61 @@ -// Copyright 2019 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.monitoring.blackbox; import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import java.util.function.Consumer; -import org.joda.time.Duration; - -/** - * {@link AutoValue} class that represents generator of actions performed at each step in {@link - * ProbingSequence}. - * - *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} - * instances. It then modifies these components on each loop iteration with the consumed {@link - * Token} and from that, generates a new {@link ProbingAction} to call.

- */ -@AutoValue -public abstract class ProbingStep implements Consumer { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * Necessary boolean to inform when to obtain next {@link Token} - */ - protected boolean isLastStep = false; - private ProbingStep nextStep; - - /** - * Time delay duration between actions. - */ - abstract Duration duration(); - - /** - * {@link Protocol} type for this step. - */ - abstract Protocol protocol(); - - /** - * {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. - */ - abstract OutboundMessageType messageTemplate(); - - /** - * {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation - * of new channels. - */ - abstract Bootstrap bootstrap(); - - - /** Default {@link AutoValue.Builder} for {@link ProbingStep}. */ - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setDuration(Duration value); - public abstract Builder setProtocol(Protocol value); - public abstract Builder setMessageTemplate(OutboundMessageType value); +public class ProbingStep implements Consumer> { - public abstract Builder setBootstrap(Bootstrap value); + private ProbingStep nextStep; - public abstract ProbingStep build(); - } - - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); - } - - void lastStep() { - isLastStep = true; - } - - void nextStep(ProbingStep step) { + public void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + public ProbingStep nextStep() { return this.nextStep; } - /** - * Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} - */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { - OutboundMessageType message = token.modifyMessage(messageTemplate()); - ProbingAction.Builder probingActionBuilder = ProbingAction.builder() - .setDelay(duration()) - .setProtocol(protocol()) - .setOutboundMessage(message) - .setHost(token.host()); - - if (token.channel() != null) { - probingActionBuilder.setChannel(token.channel()); - } else { - probingActionBuilder.setBootstrap(bootstrap()); - } - - return probingActionBuilder.build(); - } - /** - * On the last step, gets the next {@link Token}. Otherwise, uses the same one. - */ - private Token generateNextToken(Token token) { - return isLastStep ? token.next() : token; + private ProbingAction generateAction(Token token) { + // Construct a new ProbingAction and return it. + // The action is only used for one invocation + // and uses the UniqueToken provided in the argument, to + // populate fields in the action. The UniqueToken contains + // all the information needed to create an action, including + // for example the test domain name to be created/deleted and + // the channel to reuse (for ExistingChannelActions). + + return NewChannelAction.builder() + .protocol(token.protocol()) + .outboundMessage(token.message()) + .actionHandler(token.actionHandler()) + .delay(token.DEFAULT_DURATION) + .build(); + } + private Token generateNextToken(Token token) { + // Given the input token, we should be able to deduce what + // this the token for the following steps to use. If this + // step generates an action to create a domain, and the next + // one checks for its existence, the domain contained in the + // token should not change. If this is the last step in a loop + // on the other hand, the next token should contain a new + // domain name for the next loop. + return token.next(); - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the - * action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is completed is - * marked as a success, we note a success. Otherwise, if the cause of failure will either be a - * failure or error.

- */ - @Override - public void accept(Token token) { - ProbingAction currentAction; - //attempt to generate new action. On error, move on to next step - try { - currentAction = generateAction(token); - } catch (UndeterminedStateException e) { - logger.atWarning().withCause(e).log("Error in Action Generation"); - nextStep.accept(generateNextToken(token)); - return; - } - - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch (Exception e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; - } - - future.addListener(f -> { - if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success - logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - - } else { - //On a failed result, we log the failure and note either a failure or error - logger.atSevere().withCause(f.cause()).log("Did not result in future success"); - } - - if (protocol().persistentConnection()) { - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - } - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - - }); } @Override - public final String toString() { - return String.format("ProbingStep with Protocol: %s\n" - + "OutboundMessage: %s\n", - protocol(), - messageTemplate().getClass().getName()); + public void accept(Token token) { + ChannelFuture future = generateAction(token).call(); + future.addListener(f -> nextStep().accept(generateNextToken(token))); } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 676fd80d740..ca18213acf6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -16,63 +16,46 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; import javax.inject.Provider; -/** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. - */ @AutoValue public abstract class Protocol { + final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - /** - * {@link AttributeKey} that lets channel reference {@link Protocol} that created it. - */ - public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + /** Protocol name. */ + abstract String name(); - public abstract String name(); + /** Port to bind to at remote host*/ + abstract int port(); - public abstract int port(); + abstract String host(); - /** - * The {@link ChannelHandler} providers to use for the protocol, in order. - */ + /** The {@link ChannelHandler} providers to use for the protocol, in order. */ abstract ImmutableList> handlerProviders(); - /** - * Boolean that notes if connection associated with Protocol is persistent. - */ - abstract boolean persistentConnection(); - - public static Builder builder() { + static Protocol.Builder builder() { return new AutoValue_Protocol.Builder(); } - /** Default {@link AutoValue.Builder} for {@link Protocol}. */ + public static Protocol defaultImplementation(){ + return Protocol.builder().name("Default").port(8080).host("127.0.0.1").handlerProviders(ImmutableList.of()).build(); + } + @AutoValue.Builder - public abstract static class Builder { + public static abstract class Builder { - public abstract Builder setName(String value); + abstract Builder name(String value); - public abstract Builder setPort(int num); + abstract Builder host(String value); - public abstract Builder setHandlerProviders( - ImmutableList> providers); + abstract Builder port(int num); - public abstract Builder setPersistentConnection(boolean value); + abstract Builder handlerProviders(ImmutableList> providers); - public abstract Protocol build(); + abstract Protocol build(); } - @Override - public final String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); - } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java new file mode 100644 index 00000000000..0fc57f8967e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java @@ -0,0 +1,28 @@ +package google.registry.monitoring.blackbox; + + +public class TestToken extends Token { + @Override + public Protocol protocol(){ + return Protocol.defaultImplementation(); + } + + @Override + public Token next() { + return this; + } + + @Override + public O message() { + return (O) this.domainName; + } + + @Override + public ActionHandler actionHandler() { + return new ActionHandler(); + } + + public static TestToken generateNext() { + return new TestToken(); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java new file mode 100644 index 00000000000..c20ed770888 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java @@ -0,0 +1,20 @@ +package google.registry.monitoring.blackbox; + +import org.joda.time.Duration; + +abstract class Token { + public static final Duration DEFAULT_DURATION = new Duration(2000L); + protected String domainName; + + abstract Protocol protocol(); + abstract Token next(); + abstract O message(); + abstract ActionHandler actionHandler(); + + private static String newDomainName(String previousName) { + return String.format("prober-%d", System.currentTimeMillis()); + } + + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java new file mode 100644 index 00000000000..b3d22bfd24d --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java @@ -0,0 +1,16 @@ +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package google.registry.monitoring.blackbox; \ No newline at end of file From c2e6ee6f9bb76d3e3f814c2afef41f5fb3845f46 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 21 Jun 2019 14:23:16 -0400 Subject: [PATCH 072/337] Deleted unfinished features. Added ActionHandler and its Unit Tests. --- .../monitoring/blackbox/ActionHandler.java | 31 +++- .../registry/monitoring/blackbox/Main.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 70 --------- .../monitoring/blackbox/ProbingAction.java | 139 ------------------ .../monitoring/blackbox/ProbingFlows.java | 15 -- .../monitoring/blackbox/ProbingSequence.java | 42 ------ .../monitoring/blackbox/ProbingStep.java | 61 -------- .../monitoring/blackbox/Protocol.java | 61 -------- .../monitoring/blackbox/TestToken.java | 28 ---- .../registry/monitoring/blackbox/Token.java | 20 --- .../blackbox/TestActionHandler.java | 84 +++++++++++ .../monitoring/blackbox/package-info.java | 16 ++ 12 files changed, 124 insertions(+), 444 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/package-info.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java index 1437d600539..92e89102eac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -20,33 +20,50 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import java.util.function.Function; +import javax.inject.Inject; -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { private ChannelPromise finished; private Channel channel; + @Inject + public ActionHandler() {} + @Override - public ChannelFuture apply(O outboundMessage) { - // Send the request to server. + public ChannelFuture apply(Object outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + channel.writeAndFlush(outboundMessage); return finished; } @Override public void handlerAdded(ChannelHandlerContext ctx) { + //Once handler is added to channel pipeline, initialize channel and future for this handler channel = ctx.channel(); finished = ctx.newPromise(); } @Override - protected void channelRead0(ChannelHandlerContext ctx, I InboundMessage) { - // Response received, validate it, register metrics, etc. - // Once everything is done, mark the promise as success; + protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { + //Only purpose of Handler is to mark future as a success finished.setSuccess(); } + /** + *Both methods are only used for testing + */ + + public Channel getChannel() { + return channel; + } + + public ChannelPromise getFinished() { + return finished; + } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java index 61699ce033c..c093b9274f8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java @@ -2,7 +2,6 @@ public class Main { public static void main(String[] args) { - System.out.println("Hello, world!"); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index ce452e19bf0..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,70 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOutboundInvoker; -import io.netty.channel.ChannelPromise; -import io.netty.channel.DefaultChannelPromise; -import io.netty.channel.socket.nio.NioSocketChannel; -import org.joda.time.Duration; - -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - abstract Bootstrap bootstrap(); - - private Channel channel; - - @Override - public Channel channel() { - return this.channel; - } - - @Override - public ChannelFuture call() { - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(NioSocketChannel outboundChannel) - throws Exception { - addHandlers( - outboundChannel.pipeline(), protocol().handlerProviders()); - } - }); - - ChannelFuture connectionFuture = bootstrap.connect(protocol().host(), protocol().port()); - ChannelPromise finished = null; - - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - this.channel = channelFuture.channel(); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - - } - } - ); - return finished; - } - - public static ProbingAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder(); - } - - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { - - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder outboundMessage(O value); - - } - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java deleted file mode 100644 index 2ccf818a57a..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ /dev/null @@ -1,139 +0,0 @@ -// 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.monitoring.blackbox; - - -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableList; -import io.netty.bootstrap.Bootstrap; -import java.util.concurrent.TimeUnit; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; -import javax.inject.Provider; - -/** - *Class that represents given action in sequence of probing - * - */ - - -public abstract class ProbingAction implements Callable { - - /** - * timer that rate limits probing - */ - private static final Timer timer = new HashedWheelTimer(); - - /** - * @return actual Duration of delay - */ - abstract Duration delay(); - - /** - * @return message to send to server - */ - abstract O outboundMessage(); - - /** - * @return Channel object that represents connection between prober client and server - */ - abstract Channel channel(); - - /** - * @return The Protocol instance that represents action to be tested by this part in sequences - */ - abstract Protocol protocol(); - - /** - * @return The requisite instance of Action Handler, which is always the last Handler in the pipeline - */ - abstract Bootstrap bootstrap(); - abstract ActionHandler actionHandler(); - - /** - * - * @return Builder for the ProbingAction Class - */ - - /** - * The method that calls the ActionHandler to send a message down the channel pipeline - * @return future that denotes when the action has been successfully performed - */ - @Override - public ChannelFuture call() { - // Add the Handlers from the run the action - // (with delay if present), and remove the ActionHandler afterwards, - // in case the channel is to be reused later. - - ChannelPromise finished = channel().newPromise(); - timer.newTimeout(timeout -> - // Retry logic may also be added here. - actionHandler().apply(outboundMessage()).addListeners( - future -> finished.setSuccess()), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - return finished; - } - - abstract static class Builder, P extends ProbingAction> { - - public abstract B delay(Duration value); - - public abstract B outboundMessage(O value); - - public abstract B protocol(Protocol value); - - public abstract B actionHandler(ActionHandler value); - - public abstract P build(); - } - /** - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified - */ - static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } - - - - /** - * @param channelPipeline is pipeline associated with channel we want to remove handlers from - * removes all handlers from pipeline - */ - static void removeHandlers(ChannelPipeline channelPipeline) { - while (channelPipeline.first() != null) { - channelPipeline.removeFirst(); - } - } - - - - -} - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java deleted file mode 100644 index 73dfd778d69..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java +++ /dev/null @@ -1,15 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingFlows { - - public static void main(String[] args) { - ProbingSequence sequence = new ProbingSequence - .Builder() - .addStep(new ProbingStep()) - .build(); - - sequence.start(); - - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java deleted file mode 100644 index 7c14d9f0bf0..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ /dev/null @@ -1,42 +0,0 @@ -package google.registry.monitoring.blackbox; - -class ProbingSequence { - private ProbingStep firstStep; - - public void start() { - // create a new unique token; - Token token = new TestToken<>(); - firstStep.accept(token); - } - - /** - * Builder that sequentially adds steps - */ - static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - - public Builder addStep(ProbingStep step) { - if (currentStep == null) { - firstStep = step; - } else { - currentStep.nextStep(step); - } - - currentStep = step; - return this; - - } - - public ProbingSequence build() { - currentStep.nextStep(firstStep); - return new ProbingSequence(this.firstStep); - } - - } - - private ProbingSequence(ProbingStep firstStep) { - this.firstStep = firstStep; - } -} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java deleted file mode 100644 index 2e2e3575d07..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ /dev/null @@ -1,61 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import java.util.function.Consumer; - - -public class ProbingStep implements Consumer> { - - private ProbingStep nextStep; - - public void nextStep(ProbingStep step) { - this.nextStep = step; - } - - public ProbingStep nextStep() { - return this.nextStep; - } - - - - private ProbingAction generateAction(Token token) { - // Construct a new ProbingAction and return it. - // The action is only used for one invocation - // and uses the UniqueToken provided in the argument, to - // populate fields in the action. The UniqueToken contains - // all the information needed to create an action, including - // for example the test domain name to be created/deleted and - // the channel to reuse (for ExistingChannelActions). - - return NewChannelAction.builder() - .protocol(token.protocol()) - .outboundMessage(token.message()) - .actionHandler(token.actionHandler()) - .delay(token.DEFAULT_DURATION) - .build(); - - } - private Token generateNextToken(Token token) { - // Given the input token, we should be able to deduce what - // this the token for the following steps to use. If this - // step generates an action to create a domain, and the next - // one checks for its existence, the domain contained in the - // token should not change. If this is the last step in a loop - // on the other hand, the next token should contain a new - // domain name for the next loop. - return token.next(); - - } - - @Override - public void accept(Token token) { - ChannelFuture future = generateAction(token).call(); - future.addListener(f -> nextStep().accept(generateNextToken(token))); - } - - -} - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java deleted file mode 100644 index ca18213acf6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ /dev/null @@ -1,61 +0,0 @@ -// 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableList; -import io.netty.util.AttributeKey; -import io.netty.channel.ChannelHandler; -import javax.inject.Provider; - -@AutoValue -public abstract class Protocol { - final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - - /** Protocol name. */ - abstract String name(); - - /** Port to bind to at remote host*/ - abstract int port(); - - abstract String host(); - - /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - abstract ImmutableList> handlerProviders(); - - static Protocol.Builder builder() { - return new AutoValue_Protocol.Builder(); - } - - public static Protocol defaultImplementation(){ - return Protocol.builder().name("Default").port(8080).host("127.0.0.1").handlerProviders(ImmutableList.of()).build(); - } - - @AutoValue.Builder - public static abstract class Builder { - - abstract Builder name(String value); - - abstract Builder host(String value); - - abstract Builder port(int num); - - abstract Builder handlerProviders(ImmutableList> providers); - - abstract Protocol build(); - } - - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java deleted file mode 100644 index 0fc57f8967e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java +++ /dev/null @@ -1,28 +0,0 @@ -package google.registry.monitoring.blackbox; - - -public class TestToken extends Token { - @Override - public Protocol protocol(){ - return Protocol.defaultImplementation(); - } - - @Override - public Token next() { - return this; - } - - @Override - public O message() { - return (O) this.domainName; - } - - @Override - public ActionHandler actionHandler() { - return new ActionHandler(); - } - - public static TestToken generateNext() { - return new TestToken(); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java deleted file mode 100644 index c20ed770888..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java +++ /dev/null @@ -1,20 +0,0 @@ -package google.registry.monitoring.blackbox; - -import org.joda.time.Duration; - -abstract class Token { - public static final Duration DEFAULT_DURATION = new Duration(2000L); - protected String domainName; - - abstract Protocol protocol(); - abstract Token next(); - abstract O message(); - abstract ActionHandler actionHandler(); - - private static String newDomainName(String previousName) { - return String.format("prober-%d", System.currentTimeMillis()); - } - - - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java new file mode 100644 index 00000000000..091fbbbf9a4 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java @@ -0,0 +1,84 @@ +// 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelPromise; +import io.netty.channel.embedded.EmbeddedChannel; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + + +/** Unit tests for {@link ActionHandler}. */ +@RunWith(JUnit4.class) +public class TestActionHandler { + + private final ActionHandler actionHandler = new ActionHandler(); + private EmbeddedChannel channel; + + @Before + public void setup() { + channel = new EmbeddedChannel(actionHandler); + } + + @Test + public void testHandler_Params() { + //initial check on Channel Activity + assertThat(channel.isActive()).isTrue(); + + + //Ensures channel Handler points to is right what + assertThat(actionHandler.getChannel()).isEqualTo(channel); + } + + @Test + public void testHandler_Behavior() { + //initial check on Channel Activity + assertThat(channel.isActive()).isTrue(); + + + ByteBuf outboundBuffer = Unpooled.copyInt(64); + + //Use ActionHandler's write method to check if the future returned is accurate + //and that it accurately writes out the inputBuffer + assertThat(actionHandler.apply(outboundBuffer)).isEqualTo(actionHandler.getFinished()); + assertThat(channel.outboundMessages().poll()).isEqualTo(outboundBuffer); + + //Creates Promise that is set to success when something changes on actionHandler's future + ChannelPromise testPromise = channel.newPromise(); + actionHandler.getFinished().addListener(f -> testPromise.setSuccess()); + + //Ensure that before reading inbound data, actionHandler's future stays inactive + assertThat(testPromise.isSuccess()).isFalse(); + + ByteBuf inputBuffer = Unpooled.copyInt(128); + + //Check that ActionHandler doesn't do anything to inbound Buffer + assertThat(channel.writeInbound(inputBuffer)).isFalse(); + + + //ensures that actionHandler's future's listener is active and that it is set to success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(actionHandler.getFinished().isSuccess()).isTrue(); + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java new file mode 100644 index 00000000000..b3d22bfd24d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java @@ -0,0 +1,16 @@ +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package google.registry.monitoring.blackbox; \ No newline at end of file From 549be4d1aa26c01c24578a3097531f5d58765ff6 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 21 Jun 2019 14:45:36 -0400 Subject: [PATCH 073/337] Included prober subproject in settings.gradle --- settings.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings.gradle b/settings.gradle index 9b2d11de8da..0cd8f4dd707 100644 --- a/settings.gradle +++ b/settings.gradle @@ -36,3 +36,5 @@ include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' +include 'prober' + From 5c0c55110900542854a563c7150cba71f8560f85 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 24 Jun 2019 12:18:55 -0400 Subject: [PATCH 074/337] Added Protocol Class and its Basic Unit Tests --- .../monitoring/blackbox/ActionHandler.java | 69 ------------ .../monitoring/blackbox/Protocol.java | 75 +++++++++++++ .../blackbox/handlers/ActionHandler.java | 100 +++++------------- .../monitoring/blackbox/TestProtocol.java | 70 ++++++++++++ 4 files changed, 173 insertions(+), 141 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java deleted file mode 100644 index 92e89102eac..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ /dev/null @@ -1,69 +0,0 @@ -// 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.monitoring.blackbox; - -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import java.util.function.Function; -import javax.inject.Inject; - -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { - - private ChannelPromise finished; - private Channel channel; - - @Inject - public ActionHandler() {} - - @Override - public ChannelFuture apply(Object outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline - - channel.writeAndFlush(outboundMessage); - return finished; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) { - //Once handler is added to channel pipeline, initialize channel and future for this handler - channel = ctx.channel(); - finished = ctx.newPromise(); - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { - //Only purpose of Handler is to mark future as a success - - finished.setSuccess(); - } - - /** - *Both methods are only used for testing - */ - - public Channel getChannel() { - return channel; - } - - public ChannelPromise getFinished() { - return finished; - } - -} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java new file mode 100644 index 00000000000..3ddecba5af7 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -0,0 +1,75 @@ +// 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; +import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; +import javax.inject.Provider; + +@AutoValue +public abstract class Protocol { + + /** + * Default names associated with each protocol + */ + final static String EPP_PROTOCOL_NAME = "EPP"; + final static String DNS_PROTOCOL_NAME = "DNS"; + final static String WHOIS_PROTOCOL_NAME = "WHOIS"; + final static String RDAP_PROTOCOL_NAME = "RDAP"; + + final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + public boolean PERSISTENT_CONNECTION = name() == EPP_PROTOCOL_NAME; + /** + * @return name of Protocol. + */ + abstract String name(); + + /** + * @return Port to bind to at remote host + */ + abstract int port(); + + /** + * @return hostname to connect to + */ + abstract String host(); + + /** The {@link ChannelHandler} providers to use for the protocol, in order. */ + abstract ImmutableList> handlerProviders(); + + /** Builds new Protocol from @AutoValue Builder implementation*/ + static Protocol.Builder builder() { + return new AutoValue_Protocol.Builder(); + } + + + @AutoValue.Builder + public static abstract class Builder { + + abstract Builder name(String value); + + abstract Builder host(String value); + + abstract Builder port(int num); + + abstract Builder handlerProviders(ImmutableList> providers); + + abstract Protocol build(); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 6552bca3eca..54c51749aaf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,100 +14,56 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; - -/** - * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline - * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType - * >}, as it should only be passed in messages that implement the {@link InboundMessageType} - * interface.

- * - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a - * {@link - * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this - * channel is informed of the error. If the error is an instance of a {@link FailureException} - * {@code finished} is marked as a failure with cause {@link FailureException}. If it is any other - * type of error, it is treated as an {@link UndeterminedStateException} and {@code finished} set as - * a failure with the same cause as what caused the exception. Lastly, if no error is thrown, we - * know the action completed as a success, and, as such, we mark {@code finished} as a success.

- * - *

Subclasses specify further work to be done for specific kinds of channel pipelines.

- */ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +import java.util.function.Function; +import javax.inject.Inject; - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { - /** - * {@link ChannelPromise} that informs {@link ProbingAction} if response has been received. - */ private ChannelPromise finished; + private Channel channel; - /** - * Returns initialized {@link ChannelPromise} to {@link ProbingAction}. - */ - public ChannelFuture getFinishedFuture() { + @Inject + public ActionHandler() {} + + @Override + public ChannelFuture apply(Object outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + + channel.writeAndFlush(outboundMessage); return finished; } - /** - * Initializes {@link ChannelPromise} - */ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler + channel = ctx.channel(); finished = ctx.newPromise(); } - /** - * Marks {@link ChannelPromise} as success - */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { + //Only purpose of Handler is to mark future as a success - ChannelFuture unusedFuture = finished.setSuccess(); + finished.setSuccess(); } /** - * Logs the channel and pipeline that caused error, closes channel, then informs {@link - * ProbingAction} listeners of error. + *Both methods are only used for testing */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atWarning().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); - - if (cause instanceof FailureException) { - //On FailureException, we know the response is a failure. - - //Since it wasn't a success, we still want to log to see what caused the FAILURE - logger.atInfo().log(cause.getMessage()); - - //As always, inform the ProbingStep that we successfully completed this action - ChannelFuture unusedFuture = finished.setFailure(cause); - } else { - //On UndeterminedStateException, we know the response type is an error. - - //Since it wasn't a success, we still log what caused the ERROR - logger.atWarning().log(cause.getMessage()); - ChannelFuture unusedFuture = finished.setFailure(cause); + public Channel getChannel() { + return channel; + } - //As this was an ERROR in performing the action, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } + public ChannelPromise getFinished() { + return finished; } + } + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java new file mode 100644 index 00000000000..8f35843cb4c --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java @@ -0,0 +1,70 @@ +package google.registry.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.TestModule.TestProtocolModule; +import google.registry.monitoring.blackbox.TestModule.TestComponent; +import com.google.common.collect.ImmutableList; +import io.netty.channel.ChannelHandler; +import javax.inject.Inject; +import javax.inject.Provider; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Basic unit test for Protocol Class + */ +@RunWith(JUnit4.class) +public class TestProtocol { + + /** + * Stores default values that constitute a Protocol + */ + private static final String HOST_NAME = "127.0.0.1"; + private static final int PORT_NUM = 0; + private static final String NAME = "Test"; + private static final ImmutableList> HANDLERS = ImmutableList.of(); + + /** + * Test Protocol that we build + */ + private Protocol protocol; + + /** + * + * @return Protocol implementation built using fields above + */ + static Protocol defaultImplementation() { + return Protocol.builder() + .host(HOST_NAME) + .port(PORT_NUM) + .name(NAME) + .handlerProviders(HANDLERS) + .build(); + } + + /** + * Stores default implementation into private protocol field + */ + private void basicProtocol() { + protocol = TestProtocol.defaultImplementation(); + } + + + /** + * Basic unit test that insures stored values in protocol are accurate + */ + @Test + public void testProtocolAttributes() { + basicProtocol(); + assertThat(protocol.host()).isEqualTo(HOST_NAME); + assertThat(protocol.port()).isEqualTo(PORT_NUM); + assertThat(protocol.name()).isEqualTo(NAME); + assertThat(protocol.handlerProviders()).isEqualTo(HANDLERS); + } + + + +} From 901e9d489932be2f0557d8a2f16505543f943a57 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 28 Jun 2019 17:10:59 -0400 Subject: [PATCH 075/337] Added Changes Suggested by jianglai --- prober/build.gradle | 6 +- .../registry/monitoring/blackbox/Main.java | 7 -- .../monitoring/blackbox/Protocol.java | 71 +++++++++++++------ .../blackbox/handlers/ActionHandler.java | 49 ++++++++----- .../monitoring/blackbox/package-info.java | 1 - .../ActionHandlerTest.java} | 3 +- .../monitoring/blackbox/TestProtocol.java | 70 ------------------ .../monitoring/blackbox/package-info.java | 1 - 8 files changed, 86 insertions(+), 122 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Main.java rename prober/src/test/java/google/registry/monitoring/blackbox/{TestActionHandler.java => Handlers/ActionHandlerTest.java} (95%) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java diff --git a/prober/build.gradle b/prober/build.gradle index 33feefb7175..fe5e08a62f5 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'java' -createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Main') +createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') dependencies { @@ -30,7 +30,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] - compile project(':util') + //compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] @@ -42,7 +42,7 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - testCompile project(path: ':core', configuration: 'testRuntime') + //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java deleted file mode 100644 index c093b9274f8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java +++ /dev/null @@ -1,7 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Main { - public static void main(String[] args) { - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 3ddecba5af7..50a1d90a12c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -20,6 +20,11 @@ import io.netty.channel.ChannelHandler; import javax.inject.Provider; +/** + * Protocol Class packages all static variables necessary for a certain type of connection + * Both the host and the path can be changed for the same protocol + * Mainly packages the handlers necessary for the requisite channel pipeline + */ @AutoValue public abstract class Protocol { @@ -31,28 +36,49 @@ public abstract class Protocol { final static String WHOIS_PROTOCOL_NAME = "WHOIS"; final static String RDAP_PROTOCOL_NAME = "RDAP"; - final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - public boolean PERSISTENT_CONNECTION = name() == EPP_PROTOCOL_NAME; - /** - * @return name of Protocol. - */ - abstract String name(); + private String host; + private String path = ""; - /** - * @return Port to bind to at remote host - */ - abstract int port(); + /** Setter method for Protocol's host*/ + public Protocol host(String host) { + this.host = host; + return this; + } - /** - * @return hostname to connect to - */ - abstract String host(); + /** Getter method for Protocol's host*/ + public String host() { + return host; + } + + /** Setter method for Protocol's path*/ + public Protocol path(String path) { + this.path = path; + return this; + } + + /** Getter method for Protocol's path*/ + public String path() { + return path; + } + + /** If connection associated with Protocol is persistent, which is only EPP */ + public boolean persistentConnection() { + return name() == EPP_PROTOCOL_NAME; + } + + /** Protocol Name */ + public abstract String name(); + + /** Port to bind to at remote host */ + public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - abstract ImmutableList> handlerProviders(); + public abstract ImmutableList> handlerProviders(); + + + public abstract Builder toBuilder(); - /** Builds new Protocol from @AutoValue Builder implementation*/ - static Protocol.Builder builder() { + public static Protocol.Builder builder() { return new AutoValue_Protocol.Builder(); } @@ -60,16 +86,15 @@ static Protocol.Builder builder() { @AutoValue.Builder public static abstract class Builder { - abstract Builder name(String value); + public abstract Builder name(String value); - abstract Builder host(String value); + public abstract Builder port(int num); - abstract Builder port(int num); + public abstract Builder handlerProviders(ImmutableList> providers); - abstract Builder handlerProviders(ImmutableList> providers); - - abstract Protocol build(); + public abstract Protocol build(); } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 54c51749aaf..a4df56408b5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,56 +14,73 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.flogger.FluentLogger; +import com.google.common.flogger.StackSize; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.HttpResponse; import java.util.function.Function; import javax.inject.Inject; -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { +/** + * + * @param Generic Type of Inbound Message + * @param Generic Type of Outbound Message + * Abstract class that tells sends message down pipeline and + * and tells listeners to move on when the message is received. + */ +public abstract class ActionHandler extends SimpleChannelInboundHandler + implements Function { - private ChannelPromise finished; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + protected ChannelPromise finished; private Channel channel; - @Inject - public ActionHandler() {} + /** returns ChannelPromise for when inbound message is recieved + * a + * @param outboundMessage + * @return + */ @Override - public ChannelFuture apply(Object outboundMessage) { + public ChannelFuture apply(O outboundMessage) { // Sends request along Outbound Handlers on the Pipeline channel.writeAndFlush(outboundMessage); return finished; + + } + + public void resetFuture() { + finished = channel.newPromise(); } @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler + channel = ctx.channel(); finished = ctx.newPromise(); } @Override - protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { + public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ //Only purpose of Handler is to mark future as a success finished.setSuccess(); } - /** - *Both methods are only used for testing - */ - - public Channel getChannel() { - return channel; + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } - public ChannelPromise getFinished() { - return finished; - } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java index b3d22bfd24d..21c8764701c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java @@ -12,5 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -@javax.annotation.ParametersAreNonnullByDefault package google.registry.monitoring.blackbox; \ No newline at end of file diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java similarity index 95% rename from prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java rename to prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java index 091fbbbf9a4..01b93866b14 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java @@ -12,10 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.Handlers; import static com.google.common.truth.Truth.assertThat; +import google.registry.monitoring.blackbox.handlers.ActionHandler; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelPromise; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java deleted file mode 100644 index 8f35843cb4c..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java +++ /dev/null @@ -1,70 +0,0 @@ -package google.registry.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import google.registry.monitoring.blackbox.TestModule.TestProtocolModule; -import google.registry.monitoring.blackbox.TestModule.TestComponent; -import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; -import javax.inject.Inject; -import javax.inject.Provider; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Basic unit test for Protocol Class - */ -@RunWith(JUnit4.class) -public class TestProtocol { - - /** - * Stores default values that constitute a Protocol - */ - private static final String HOST_NAME = "127.0.0.1"; - private static final int PORT_NUM = 0; - private static final String NAME = "Test"; - private static final ImmutableList> HANDLERS = ImmutableList.of(); - - /** - * Test Protocol that we build - */ - private Protocol protocol; - - /** - * - * @return Protocol implementation built using fields above - */ - static Protocol defaultImplementation() { - return Protocol.builder() - .host(HOST_NAME) - .port(PORT_NUM) - .name(NAME) - .handlerProviders(HANDLERS) - .build(); - } - - /** - * Stores default implementation into private protocol field - */ - private void basicProtocol() { - protocol = TestProtocol.defaultImplementation(); - } - - - /** - * Basic unit test that insures stored values in protocol are accurate - */ - @Test - public void testProtocolAttributes() { - basicProtocol(); - assertThat(protocol.host()).isEqualTo(HOST_NAME); - assertThat(protocol.port()).isEqualTo(PORT_NUM); - assertThat(protocol.name()).isEqualTo(NAME); - assertThat(protocol.handlerProviders()).isEqualTo(HANDLERS); - } - - - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java index b3d22bfd24d..21c8764701c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java @@ -12,5 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -@javax.annotation.ParametersAreNonnullByDefault package google.registry.monitoring.blackbox; \ No newline at end of file From bacced89c564790c6f28e7b6fee0d6842213155d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:06:18 -0400 Subject: [PATCH 076/337] Fixed Gitignore to take out AutoValue generated code --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 327b22fe2e7..199c4fe3979 100644 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,9 @@ nomulus.iws # Javascript output **/out/* +# AutoValue generated code +AutoValue_.*.java + ###################################################################### # Python Ignores From d5cc0cba94dd2098cc4770a5d65d1690bae42354 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:07:59 -0400 Subject: [PATCH 077/337] Removed AutoValue java files --- .../blackbox/AutoValue_NewChannelAction.java | 181 ------------------ .../blackbox/AutoValue_ProbingAction.java | 118 ------------ .../blackbox/AutoValue_Protocol.java | 153 --------------- 3 files changed, 452 deletions(-) delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java deleted file mode 100644 index 6f818f03a28..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java +++ /dev/null @@ -1,181 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import io.netty.bootstrap.Bootstrap; -import javax.annotation.Generated; -import org.joda.time.Duration; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_NewChannelAction extends NewChannelAction { - - private final Duration delay; - - private final O outboundMessage; - - private final Protocol protocol; - - private final ActionHandler actionHandler; - - private final Bootstrap bootstrap; - - private AutoValue_NewChannelAction( - Duration delay, - O outboundMessage, - Protocol protocol, - ActionHandler actionHandler, - Bootstrap bootstrap) { - this.delay = delay; - this.outboundMessage = outboundMessage; - this.protocol = protocol; - this.actionHandler = actionHandler; - this.bootstrap = bootstrap; - } - - @Override - Duration delay() { - return delay; - } - - @Override - O outboundMessage() { - return outboundMessage; - } - - @Override - Protocol protocol() { - return protocol; - } - - @Override - ActionHandler actionHandler() { - return actionHandler; - } - - @Override - Bootstrap bootstrap() { - return bootstrap; - } - - @Override - public String toString() { - return "NewChannelAction{" - + "delay=" + delay + ", " - + "outboundMessage=" + outboundMessage + ", " - + "protocol=" + protocol + ", " - + "actionHandler=" + actionHandler + ", " - + "bootstrap=" + bootstrap - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof NewChannelAction) { - NewChannelAction that = (NewChannelAction) o; - return this.delay.equals(that.delay()) - && this.outboundMessage.equals(that.outboundMessage()) - && this.protocol.equals(that.protocol()) - && this.actionHandler.equals(that.actionHandler()) - && this.bootstrap.equals(that.bootstrap()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= delay.hashCode(); - h$ *= 1000003; - h$ ^= outboundMessage.hashCode(); - h$ *= 1000003; - h$ ^= protocol.hashCode(); - h$ *= 1000003; - h$ ^= actionHandler.hashCode(); - h$ *= 1000003; - h$ ^= bootstrap.hashCode(); - return h$; - } - - static final class Builder extends NewChannelAction.Builder { - private Duration delay; - private O outboundMessage; - private Protocol protocol; - private ActionHandler actionHandler; - private Bootstrap bootstrap; - Builder() { - } - @Override - public NewChannelAction.Builder delay(Duration delay) { - if (delay == null) { - throw new NullPointerException("Null delay"); - } - this.delay = delay; - return this; - } - @Override - public NewChannelAction.Builder outboundMessage(O outboundMessage) { - if (outboundMessage == null) { - throw new NullPointerException("Null outboundMessage"); - } - this.outboundMessage = outboundMessage; - return this; - } - @Override - public NewChannelAction.Builder protocol(Protocol protocol) { - if (protocol == null) { - throw new NullPointerException("Null protocol"); - } - this.protocol = protocol; - return this; - } - @Override - public NewChannelAction.Builder actionHandler(ActionHandler actionHandler) { - if (actionHandler == null) { - throw new NullPointerException("Null actionHandler"); - } - this.actionHandler = actionHandler; - return this; - } - @Override - public NewChannelAction.Builder bootstrap(Bootstrap bootstrap) { - if (bootstrap == null) { - throw new NullPointerException("Null bootstrap"); - } - this.bootstrap = bootstrap; - return this; - } - @Override - public NewChannelAction build() { - String missing = ""; - if (this.delay == null) { - missing += " delay"; - } - if (this.outboundMessage == null) { - missing += " outboundMessage"; - } - if (this.protocol == null) { - missing += " protocol"; - } - if (this.actionHandler == null) { - missing += " actionHandler"; - } - if (this.bootstrap == null) { - missing += " bootstrap"; - } - if (!missing.isEmpty()) { - throw new IllegalStateException("Missing required properties:" + missing); - } - return new AutoValue_NewChannelAction( - this.delay, - this.outboundMessage, - this.protocol, - this.actionHandler, - this.bootstrap); - } - } - -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java deleted file mode 100644 index 26f560b145b..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java +++ /dev/null @@ -1,118 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import io.netty.channel.Channel; -import javax.annotation.Generated; -import org.joda.time.Duration; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_ProbingAction extends ProbingAction { - - private final Duration delay; - - private final O outboundMessage; - - private final Channel channel; - - private final Protocol protocol; - - private final ActionHandler actionHandler; - - AutoValue_ProbingAction( - Duration delay, - O outboundMessage, - Channel channel, - Protocol protocol, - ActionHandler actionHandler) { - if (delay == null) { - throw new NullPointerException("Null delay"); - } - this.delay = delay; - if (outboundMessage == null) { - throw new NullPointerException("Null outboundMessage"); - } - this.outboundMessage = outboundMessage; - if (channel == null) { - throw new NullPointerException("Null channel"); - } - this.channel = channel; - if (protocol == null) { - throw new NullPointerException("Null protocol"); - } - this.protocol = protocol; - if (actionHandler == null) { - throw new NullPointerException("Null actionHandler"); - } - this.actionHandler = actionHandler; - } - - @Override - Duration delay() { - return delay; - } - - @Override - O outboundMessage() { - return outboundMessage; - } - - @Override - Channel channel() { - return channel; - } - - @Override - Protocol protocol() { - return protocol; - } - - @Override - ActionHandler actionHandler() { - return actionHandler; - } - - @Override - public String toString() { - return "ProbingAction{" - + "delay=" + delay + ", " - + "outboundMessage=" + outboundMessage + ", " - + "channel=" + channel + ", " - + "protocol=" + protocol + ", " - + "actionHandler=" + actionHandler - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof ProbingAction) { - ProbingAction that = (ProbingAction) o; - return this.delay.equals(that.delay()) - && this.outboundMessage.equals(that.outboundMessage()) - && this.channel.equals(that.channel()) - && this.protocol.equals(that.protocol()) - && this.actionHandler.equals(that.actionHandler()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= delay.hashCode(); - h$ *= 1000003; - h$ ^= outboundMessage.hashCode(); - h$ *= 1000003; - h$ ^= channel.hashCode(); - h$ *= 1000003; - h$ ^= protocol.hashCode(); - h$ *= 1000003; - h$ ^= actionHandler.hashCode(); - return h$; - } - -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java deleted file mode 100644 index 3247cbdd310..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java +++ /dev/null @@ -1,153 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_Protocol extends Protocol { - - private final String name; - - private final int port; - - private final String host; - - private final ImmutableList> handlerProviders; - - private AutoValue_Protocol( - String name, - int port, - String host, - ImmutableList> handlerProviders) { - this.name = name; - this.port = port; - this.host = host; - this.handlerProviders = handlerProviders; - } - - @Override - String name() { - return name; - } - - @Override - int port() { - return port; - } - - @Override - String host() { - return host; - } - - @Override - ImmutableList> handlerProviders() { - return handlerProviders; - } - - @Override - public String toString() { - return "Protocol{" - + "name=" + name + ", " - + "port=" + port + ", " - + "host=" + host + ", " - + "handlerProviders=" + handlerProviders - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof Protocol) { - Protocol that = (Protocol) o; - return this.name.equals(that.name()) - && this.port == that.port() - && this.host.equals(that.host()) - && this.handlerProviders.equals(that.handlerProviders()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= name.hashCode(); - h$ *= 1000003; - h$ ^= port; - h$ *= 1000003; - h$ ^= host.hashCode(); - h$ *= 1000003; - h$ ^= handlerProviders.hashCode(); - return h$; - } - - static final class Builder extends Protocol.Builder { - private String name; - private Integer port; - private String host; - private ImmutableList> handlerProviders; - Builder() { - } - @Override - Protocol.Builder name(String name) { - if (name == null) { - throw new NullPointerException("Null name"); - } - this.name = name; - return this; - } - @Override - Protocol.Builder port(int port) { - this.port = port; - return this; - } - @Override - Protocol.Builder host(String host) { - if (host == null) { - throw new NullPointerException("Null host"); - } - this.host = host; - return this; - } - @Override - Protocol.Builder handlerProviders(ImmutableList> handlerProviders) { - if (handlerProviders == null) { - throw new NullPointerException("Null handlerProviders"); - } - this.handlerProviders = handlerProviders; - return this; - } - @Override - Protocol build() { - String missing = ""; - if (this.name == null) { - missing += " name"; - } - if (this.port == null) { - missing += " port"; - } - if (this.host == null) { - missing += " host"; - } - if (this.handlerProviders == null) { - missing += " handlerProviders"; - } - if (!missing.isEmpty()) { - throw new IllegalStateException("Missing required properties:" + missing); - } - return new AutoValue_Protocol( - this.name, - this.port, - this.host, - this.handlerProviders); - } - } - -} From 19d0238fabbb813d2fba6abbc38af8a40d74b65f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:28:29 -0400 Subject: [PATCH 078/337] Added gitignore within prober --- .../blackbox/ActionHandler_Factory.java | 25 +++ .../DaggerProberModule_ProberComponent.java | 154 +++++++++++++++++ ...aggerWebWhoisModule_WebWhoisComponent.java | 119 ++++++++++++++ ...berModule_ProvideHttpWhoIsPortFactory.java | 29 ++++ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoIsPortFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 29 ++++ ...odule_ProvidePortToProtocolMapFactory.java | 42 +++++ .../blackbox/ProbingStepWeb_Factory.java | 30 ++++ .../blackbox/ProbingStep_Factory.java | 27 +++ .../blackbox/TestToken_Factory.java | 45 +++++ .../blackbox/TestToken_MembersInjector.java | 30 ++++ .../TokenModule_DomainNameFactory.java | 27 +++ .../TokenModule_ProvideTokenFactory.java | 35 ++++ .../blackbox/Token_MembersInjector.java | 31 ++++ .../Tokens/WebWhoisToken_Factory.java | 25 +++ .../WebWhoisModule_HttpWhoisHostFactory.java | 28 ++++ .../WebWhoisModule_HttpWhoisPathFactory.java | 28 ++++ .../WebWhoisModule_HttpWhoisPortFactory.java | 26 +++ .../WebWhoisModule_HttpsWhoisHostFactory.java | 29 ++++ .../WebWhoisModule_HttpsWhoisPathFactory.java | 29 ++++ .../WebWhoisModule_HttpsWhoisPortFactory.java | 26 +++ ...sModule_ProvideHttpClientCodecFactory.java | 31 ++++ ...le_ProvideHttpObjectAggregatorFactory.java | 31 ++++ ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ++++ ...oisModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ++++++ ...isModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ++++++ ...WhoisModule_ProvideSslProviderFactory.java | 30 ++++ ...viderHttpWhoisHandlerProvidersFactory.java | 58 +++++++ ...iderHttpsWhoisHandlerProvidersFactory.java | 75 +++++++++ .../blackbox/WebWhoisToken_Factory.java | 25 +++ .../handlers/ActionHandler_Factory.java | 25 +++ .../handlers/RedirectHandler_Factory.java | 25 +++ .../SslClientInitializer_Factory.java | 35 ++++ .../handlers/WebWhoIsHandler_Factory.java | 25 +++ .../WebWhoisActionHandler_Factory.java | 25 +++ .../DaggerProberModule_ProberComponent.java | 155 ++++++++++++++++++ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...odule_ProvidePortToProtocolMapFactory.java | 43 +++++ .../TokenModule_DomainNameFactory.java | 27 +++ .../TokenModule_ProvideTokenFactory.java | 35 ++++ ...sModule_ProvideHttpClientCodecFactory.java | 31 ++++ ...le_ProvideHttpObjectAggregatorFactory.java | 31 ++++ ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 54 ++++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 54 ++++++ ...WhoisModule_ProvideSslProviderFactory.java | 30 ++++ ...viderHttpWhoisHandlerProvidersFactory.java | 58 +++++++ ...iderHttpsWhoisHandlerProvidersFactory.java | 75 +++++++++ .../DaggerProberModule_ProberComponent.java | 154 +++++++++++++++++ .../DaggerTestModule_TestComponent.java | 46 ++++++ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...odule_ProvidePortToProtocolMapFactory.java | 42 +++++ .../blackbox/TestHandler_Factory.java | 25 +++ .../TestModule_ProvideHandlersFactory.java | 38 +++++ .../TestProtocol_MembersInjector.java | 36 ++++ .../TokenModule_DomainNameFactory.java | 27 +++ .../TokenModule_ProvideTokenFactory.java | 35 ++++ ...sModule_ProvideHttpClientCodecFactory.java | 31 ++++ ...le_ProvideHttpObjectAggregatorFactory.java | 31 ++++ ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ++++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ++++++ ...WhoisModule_ProvideSslProviderFactory.java | 30 ++++ ...viderHttpWhoisHandlerProvidersFactory.java | 58 +++++++ ...iderHttpsWhoisHandlerProvidersFactory.java | 75 +++++++++ 72 files changed, 3018 insertions(+) create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java new file mode 100644 index 00000000000..8a727c63bbb --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ActionHandler_Factory implements Factory { + private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); + + @Override + public ActionHandler get() { + return new ActionHandler(); + } + + public static ActionHandler_Factory create() { + return INSTANCE; + } + + public static ActionHandler newActionHandler() { + return new ActionHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java new file mode 100644 index 00000000000..39af08b1e60 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java @@ -0,0 +1,154 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { + private final ProberModule proberModule; + + private Provider provideHttpWhoisPortProvider; + + private Provider provideHttpWhoisHostProvider; + + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider provideHttpsWhoisPortProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerProberModule_ProberComponent( + ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { + this.proberModule = proberModuleParam; + initialize(proberModuleParam, webWhoisModuleParam); + } + + public static Builder builder() { + return new Builder(); + } + + public static ProberModule.ProberComponent create() { + return new Builder().build(); + } + + private Set getSetOfProtocol() { + return ImmutableSet.of( + provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); + } + + private WebWhoisToken getWebWhoisToken() { + return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); + } + + @SuppressWarnings("unchecked") + private void initialize( + final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { + this.provideHttpWhoisPortProvider = + ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); + this.provideHttpWhoisHostProvider = + WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + provideHttpWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpWhoisHandlerProvidersProvider)); + this.provideHttpsWhoisPortProvider = + ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + provideHttpsWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public ImmutableMap providePortToProtocolMap() { + return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( + proberModule, getSetOfProtocol()); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); + } + + public static final class Builder { + private ProberModule proberModule; + + private WebWhoisModule webWhoisModule; + + private Builder() {} + + public Builder proberModule(ProberModule proberModule) { + this.proberModule = Preconditions.checkNotNull(proberModule); + return this; + } + + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public ProberModule.ProberComponent build() { + if (proberModule == null) { + this.proberModule = new ProberModule(); + } + if (webWhoisModule == null) { + this.webWhoisModule = new WebWhoisModule(); + } + return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); + } + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java new file mode 100644 index 00000000000..ba272c4730a --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java @@ -0,0 +1,119 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerWebWhoisModule_WebWhoisComponent + implements WebWhoisModule.WebWhoisComponent { + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerWebWhoisModule_WebWhoisComponent() { + + initialize(); + } + + public static Builder builder() { + return new Builder(); + } + + public static WebWhoisModule.WebWhoisComponent create() { + return new Builder().build(); + } + + @SuppressWarnings("unchecked") + private void initialize() { + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + WebWhoisModule_HttpWhoisPortFactory.create(), + WebWhoisModule_HttpWhoisHostFactory.create(), + providerHttpWhoisHandlerProvidersProvider)); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + WebWhoisModule_HttpsWhoisPortFactory.create(), + WebWhoisModule_HttpsWhoisHostFactory.create(), + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public Protocol provideHttpWhoisProtocol() { + return provideHttpWhoisProtocolProvider.get(); + } + + @Override + public Protocol provideHttpsWhoisProtocol() { + return provideHttpsWhoisProtocolProvider.get(); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(); + } + + public static final class Builder { + private Builder() {} + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public WebWhoisModule.WebWhoisComponent build() { + return new DaggerWebWhoisModule_WebWhoisComponent(); + } + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java new file mode 100644 index 00000000000..659d36c8249 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoIsPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoIsPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoIsPort(module); + } + + public static ProberModule_ProvideHttpWhoIsPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoIsPortFactory(module); + } + + public static int proxyProvideHttpWhoIsPort(ProberModule instance) { + return instance.provideHttpWhoIsPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..93f9e4f9f48 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(ProberModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..4d560ae3c94 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisProtocolFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisProtocol(module); + } + + public static ProberModule_ProvideHttpWhoisProtocolFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisProtocolFactory(module); + } + + public static int proxyProvideHttpWhoisProtocol(ProberModule instance) { + return instance.provideHttpWhoisProtocol(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java new file mode 100644 index 00000000000..a49efddd550 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoIsPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoIsPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoIsPort(module); + } + + public static ProberModule_ProvideHttpsWhoIsPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoIsPortFactory(module); + } + + public static int proxyProvideHttpsWhoIsPort(ProberModule instance) { + return instance.provideHttpsWhoIsPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..0aee5faf959 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(ProberModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..faaae10cb72 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisProtocolFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisProtocol(module); + } + + public static ProberModule_ProvideHttpsWhoisProtocolFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisProtocolFactory(module); + } + + public static int proxyProvideHttpsWhoisProtocol(ProberModule instance) { + return instance.provideHttpsWhoisProtocol(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java new file mode 100644 index 00000000000..7ab2e4e9dd9 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java @@ -0,0 +1,42 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableMap; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvidePortToProtocolMapFactory + implements Factory> { + private final ProberModule module; + + private final Provider> protocolSetProvider; + + public ProberModule_ProvidePortToProtocolMapFactory( + ProberModule module, Provider> protocolSetProvider) { + this.module = module; + this.protocolSetProvider = protocolSetProvider; + } + + @Override + public ImmutableMap get() { + return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); + } + + public static ProberModule_ProvidePortToProtocolMapFactory create( + ProberModule module, Provider> protocolSetProvider) { + return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); + } + + public static ImmutableMap proxyProvidePortToProtocolMap( + ProberModule instance, Set protocolSet) { + return Preconditions.checkNotNull( + instance.providePortToProtocolMap(protocolSet), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java new file mode 100644 index 00000000000..a8d428b93c2 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProbingStepWeb_Factory implements Factory { + private final Provider protocolProvider; + + public ProbingStepWeb_Factory(Provider protocolProvider) { + this.protocolProvider = protocolProvider; + } + + @Override + public ProbingStepWeb get() { + return new ProbingStepWeb(protocolProvider.get()); + } + + public static ProbingStepWeb_Factory create(Provider protocolProvider) { + return new ProbingStepWeb_Factory(protocolProvider); + } + + public static ProbingStepWeb newProbingStepWeb(Protocol protocol) { + return new ProbingStepWeb(protocol); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java new file mode 100644 index 00000000000..1e8ba7f6af6 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProbingStep_Factory implements Factory> { + @SuppressWarnings("rawtypes") + private static final ProbingStep_Factory INSTANCE = new ProbingStep_Factory(); + + @Override + public ProbingStep get() { + return new ProbingStep(); + } + + @SuppressWarnings("unchecked") + public static ProbingStep_Factory create() { + return INSTANCE; + } + + public static ProbingStep newProbingStep() { + return new ProbingStep(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java new file mode 100644 index 00000000000..fd4bf43308d --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java @@ -0,0 +1,45 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestToken_Factory implements Factory { + private final Provider actionHandlerProvider; + + private final Provider domainNameProvider; + + private final Provider protocolProvider; + + public TestToken_Factory( + Provider actionHandlerProvider, + Provider domainNameProvider, + Provider protocolProvider) { + this.actionHandlerProvider = actionHandlerProvider; + this.domainNameProvider = domainNameProvider; + this.protocolProvider = protocolProvider; + } + + @Override + public TestToken get() { + TestToken instance = new TestToken(actionHandlerProvider.get(), domainNameProvider.get()); + TestToken_MembersInjector.injectProtocol(instance, protocolProvider.get()); + return instance; + } + + public static TestToken_Factory create( + Provider actionHandlerProvider, + Provider domainNameProvider, + Provider protocolProvider) { + return new TestToken_Factory(actionHandlerProvider, domainNameProvider, protocolProvider); + } + + public static TestToken newTestToken(ActionHandler actionHandler, String domainName) { + return new TestToken(actionHandler, domainName); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java new file mode 100644 index 00000000000..db846ba4a36 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.MembersInjector; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestToken_MembersInjector implements MembersInjector { + private final Provider protocolProvider; + + public TestToken_MembersInjector(Provider protocolProvider) { + this.protocolProvider = protocolProvider; + } + + public static MembersInjector create(Provider protocolProvider) { + return new TestToken_MembersInjector(protocolProvider); + } + + @Override + public void injectMembers(TestToken instance) { + injectProtocol(instance, protocolProvider.get()); + } + + public static void injectProtocol(TestToken instance, Protocol protocol) { + instance.protocol = protocol; + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java new file mode 100644 index 00000000000..1dc41bf0e16 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_DomainNameFactory implements Factory { + private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); + + @Override + public String get() { + return proxyDomainName(); + } + + public static TokenModule_DomainNameFactory create() { + return INSTANCE; + } + + public static String proxyDomainName() { + return Preconditions.checkNotNull( + TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java new file mode 100644 index 00000000000..afc66775c9d --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_ProvideTokenFactory implements Factory { + private final Provider tokenProvider; + + public TokenModule_ProvideTokenFactory(Provider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public Token get() { + return proxyProvideToken(tokenProvider.get()); + } + + public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { + return new TokenModule_ProvideTokenFactory(tokenProvider); + } + + public static Token proxyProvideToken(WebWhoisToken token) { + return Preconditions.checkNotNull( + TokenModule.provideToken(token), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java new file mode 100644 index 00000000000..feab7f7d227 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.MembersInjector; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class Token_MembersInjector implements MembersInjector { + private final Provider actionHandlerProvider; + + public Token_MembersInjector(Provider actionHandlerProvider) { + this.actionHandlerProvider = actionHandlerProvider; + } + + public static MembersInjector create(Provider actionHandlerProvider) { + return new Token_MembersInjector(actionHandlerProvider); + } + + @Override + public void injectMembers(Token instance) { + injectActionHandler(instance, actionHandlerProvider.get()); + } + + public static void injectActionHandler(Object instance, ActionHandler actionHandler) { + ((Token) instance).actionHandler = actionHandler; + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java new file mode 100644 index 00000000000..3d153c08fdb --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.Tokens; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisToken_Factory implements Factory { + private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); + + @Override + public WebWhoisToken get() { + return new WebWhoisToken(); + } + + public static WebWhoisToken_Factory create() { + return INSTANCE; + } + + public static WebWhoisToken newWebWhoisToken() { + return new WebWhoisToken(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java new file mode 100644 index 00000000000..f2f34a674d3 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java @@ -0,0 +1,28 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpWhoisHostFactory implements Factory { + private static final WebWhoisModule_HttpWhoisHostFactory INSTANCE = + new WebWhoisModule_HttpWhoisHostFactory(); + + @Override + public String get() { + return proxyHttpWhoisHost(); + } + + public static WebWhoisModule_HttpWhoisHostFactory create() { + return INSTANCE; + } + + public static String proxyHttpWhoisHost() { + return Preconditions.checkNotNull( + WebWhoisModule.httpWhoisHost(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java new file mode 100644 index 00000000000..67ab24c06fd --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java @@ -0,0 +1,28 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpWhoisPathFactory implements Factory { + private static final WebWhoisModule_HttpWhoisPathFactory INSTANCE = + new WebWhoisModule_HttpWhoisPathFactory(); + + @Override + public String get() { + return proxyHttpWhoisPath(); + } + + public static WebWhoisModule_HttpWhoisPathFactory create() { + return INSTANCE; + } + + public static String proxyHttpWhoisPath() { + return Preconditions.checkNotNull( + WebWhoisModule.httpWhoisPath(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java new file mode 100644 index 00000000000..4a29a990b67 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java @@ -0,0 +1,26 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpWhoisPortFactory implements Factory { + private static final WebWhoisModule_HttpWhoisPortFactory INSTANCE = + new WebWhoisModule_HttpWhoisPortFactory(); + + @Override + public Integer get() { + return proxyHttpWhoisPort(); + } + + public static WebWhoisModule_HttpWhoisPortFactory create() { + return INSTANCE; + } + + public static int proxyHttpWhoisPort() { + return WebWhoisModule.httpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java new file mode 100644 index 00000000000..f8a7fae07a8 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpsWhoisHostFactory implements Factory { + private static final WebWhoisModule_HttpsWhoisHostFactory INSTANCE = + new WebWhoisModule_HttpsWhoisHostFactory(); + + @Override + public String get() { + return proxyHttpsWhoisHost(); + } + + public static WebWhoisModule_HttpsWhoisHostFactory create() { + return INSTANCE; + } + + public static String proxyHttpsWhoisHost() { + return Preconditions.checkNotNull( + WebWhoisModule.httpsWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java new file mode 100644 index 00000000000..4cabb7b5384 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpsWhoisPathFactory implements Factory { + private static final WebWhoisModule_HttpsWhoisPathFactory INSTANCE = + new WebWhoisModule_HttpsWhoisPathFactory(); + + @Override + public String get() { + return proxyHttpsWhoisPath(); + } + + public static WebWhoisModule_HttpsWhoisPathFactory create() { + return INSTANCE; + } + + public static String proxyHttpsWhoisPath() { + return Preconditions.checkNotNull( + WebWhoisModule.httpsWhoisPath(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java new file mode 100644 index 00000000000..30f4564213a --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java @@ -0,0 +1,26 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpsWhoisPortFactory implements Factory { + private static final WebWhoisModule_HttpsWhoisPortFactory INSTANCE = + new WebWhoisModule_HttpsWhoisPortFactory(); + + @Override + public Integer get() { + return proxyHttpsWhoisPort(); + } + + public static WebWhoisModule_HttpsWhoisPortFactory create() { + return INSTANCE; + } + + public static int proxyHttpsWhoisPort() { + return WebWhoisModule.httpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java new file mode 100644 index 00000000000..7c756174314 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpClientCodec; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpClientCodecFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = + new WebWhoisModule_ProvideHttpClientCodecFactory(); + + @Override + public HttpClientCodec get() { + return proxyProvideHttpClientCodec(); + } + + public static WebWhoisModule_ProvideHttpClientCodecFactory create() { + return INSTANCE; + } + + public static HttpClientCodec proxyProvideHttpClientCodec() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpClientCodec(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java new file mode 100644 index 00000000000..20785cde372 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = + new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); + + @Override + public HttpObjectAggregator get() { + return proxyProvideHttpObjectAggregator(); + } + + public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { + return INSTANCE; + } + + public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpObjectAggregator(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java new file mode 100644 index 00000000000..7087ab940bc --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java @@ -0,0 +1,32 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public String get() { + return proxyProvideHttpWhoisHost(module); + } + + public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); + } + + public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { + return Preconditions.checkNotNull( + instance.provideHttpWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..a4aaf24978e --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisPortFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisPortFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static WebWhoisModule_ProvideHttpWhoisPortFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(WebWhoisModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..ed7e62f3a5f --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final Provider httpWhoisPortProvider; + + private final Provider httpWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpWhoisProtocolFactory( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpWhoisPortProvider = httpWhoisPortProvider; + this.httpWhoisHostProvider = httpWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpWhoisProtocol( + httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( + httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpWhoisProtocol( + int httpWhoisPort, + String httpWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..c3d7c6546e5 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisPortFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpsWhoisPortFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static WebWhoisModule_ProvideHttpsWhoisPortFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(WebWhoisModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..4ab50681eea --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final Provider httpsWhoisPortProvider; + + private final Provider httpsWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpsWhoisPortProvider = httpsWhoisPortProvider; + this.httpsWhoisHostProvider = httpsWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpsWhoisProtocol( + httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpsWhoisProtocol( + int httpsWhoisPort, + String httpsWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java new file mode 100644 index 00000000000..7579cc752cf --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { + private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = + new WebWhoisModule_ProvideSslProviderFactory(); + + @Override + public SslProvider get() { + return proxyProvideSslProvider(); + } + + public static WebWhoisModule_ProvideSslProviderFactory create() { + return INSTANCE; + } + + public static SslProvider proxyProvideSslProvider() { + return Preconditions.checkNotNull( + WebWhoisModule.provideSslProvider(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..37431babcb9 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java @@ -0,0 +1,58 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpWhoisHandlerProviders( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..adf393894e8 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java @@ -0,0 +1,75 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider> sslClientInitializerProvider; + + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.sslClientInitializerProvider = sslClientInitializerProvider; + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpsWhoisHandlerProviders( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java new file mode 100644 index 00000000000..6c840214a11 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisToken_Factory implements Factory { + private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); + + @Override + public WebWhoisToken get() { + return new WebWhoisToken(); + } + + public static WebWhoisToken_Factory create() { + return INSTANCE; + } + + public static WebWhoisToken newWebWhoisToken() { + return new WebWhoisToken(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java new file mode 100644 index 00000000000..d94df8b392f --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ActionHandler_Factory implements Factory { + private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); + + @Override + public ActionHandler get() { + return new ActionHandler(); + } + + public static ActionHandler_Factory create() { + return INSTANCE; + } + + public static ActionHandler newActionHandler() { + return new ActionHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java new file mode 100644 index 00000000000..ddf10cf830b --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class RedirectHandler_Factory implements Factory { + private static final RedirectHandler_Factory INSTANCE = new RedirectHandler_Factory(); + + @Override + public RedirectHandler get() { + return new RedirectHandler(); + } + + public static RedirectHandler_Factory create() { + return INSTANCE; + } + + public static RedirectHandler newRedirectHandler() { + return new RedirectHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java new file mode 100644 index 00000000000..7fa480f418e --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import io.netty.channel.Channel; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class SslClientInitializer_Factory + implements Factory> { + private final Provider sslProvider; + + public SslClientInitializer_Factory(Provider sslProvider) { + this.sslProvider = sslProvider; + } + + @Override + public SslClientInitializer get() { + return new SslClientInitializer(sslProvider.get()); + } + + public static SslClientInitializer_Factory create( + Provider sslProvider) { + return new SslClientInitializer_Factory(sslProvider); + } + + public static SslClientInitializer newSslClientInitializer( + SslProvider sslProvider) { + return new SslClientInitializer(sslProvider); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java new file mode 100644 index 00000000000..26b68fdc09c --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoIsHandler_Factory implements Factory { + private static final WebWhoIsHandler_Factory INSTANCE = new WebWhoIsHandler_Factory(); + + @Override + public WebWhoIsHandler get() { + return new WebWhoIsHandler(); + } + + public static WebWhoIsHandler_Factory create() { + return INSTANCE; + } + + public static WebWhoIsHandler newWebWhoIsHandler() { + return new WebWhoIsHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java new file mode 100644 index 00000000000..dc008e1a724 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisActionHandler_Factory implements Factory { + private static final WebWhoisActionHandler_Factory INSTANCE = new WebWhoisActionHandler_Factory(); + + @Override + public WebWhoisActionHandler get() { + return new WebWhoisActionHandler(); + } + + public static WebWhoisActionHandler_Factory create() { + return INSTANCE; + } + + public static WebWhoisActionHandler newWebWhoisActionHandler() { + return new WebWhoisActionHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java new file mode 100644 index 00000000000..b7971395941 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java @@ -0,0 +1,155 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { + private final ProberModule proberModule; + + private Provider provideHttpWhoisPortProvider; + + private Provider provideHttpWhoisHostProvider; + + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider provideHttpsWhoisPortProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerProberModule_ProberComponent( + ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { + this.proberModule = proberModuleParam; + initialize(proberModuleParam, webWhoisModuleParam); + } + + public static Builder builder() { + return new Builder(); + } + + public static ProberModule.ProberComponent create() { + return new Builder().build(); + } + + private Set getSetOfProtocol() { + return ImmutableSet.of( + provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); + } + + private WebWhoisToken getWebWhoisToken() { + return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); + } + + @SuppressWarnings("unchecked") + private void initialize( + final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { + this.provideHttpWhoisPortProvider = + ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); + this.provideHttpWhoisHostProvider = + WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + provideHttpWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpWhoisHandlerProvidersProvider)); + this.provideHttpsWhoisPortProvider = + ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + provideHttpsWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public ImmutableMap providePortToProtocolMap() { + return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( + proberModule, getSetOfProtocol()); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); + } + + public static final class Builder { + private ProberModule proberModule; + + private WebWhoisModule webWhoisModule; + + private Builder() {} + + public Builder proberModule(ProberModule proberModule) { + this.proberModule = Preconditions.checkNotNull(proberModule); + return this; + } + + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public ProberModule.ProberComponent build() { + if (proberModule == null) { + this.proberModule = new ProberModule(); + } + if (webWhoisModule == null) { + this.webWhoisModule = new WebWhoisModule(); + } + return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); + } + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..955698498db --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(ProberModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..0b97c8dbb72 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(ProberModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java new file mode 100644 index 00000000000..e0597aa25f5 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java @@ -0,0 +1,43 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableMap; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvidePortToProtocolMapFactory + implements Factory> { + private final ProberModule module; + + private final Provider> protocolSetProvider; + + public ProberModule_ProvidePortToProtocolMapFactory( + ProberModule module, Provider> protocolSetProvider) { + this.module = module; + this.protocolSetProvider = protocolSetProvider; + } + + @Override + public ImmutableMap get() { + return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); + } + + public static ProberModule_ProvidePortToProtocolMapFactory create( + ProberModule module, Provider> protocolSetProvider) { + return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); + } + + public static ImmutableMap proxyProvidePortToProtocolMap( + ProberModule instance, Set protocolSet) { + return Preconditions.checkNotNull( + instance.providePortToProtocolMap(protocolSet), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java new file mode 100644 index 00000000000..20e2ca11502 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_DomainNameFactory implements Factory { + private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); + + @Override + public String get() { + return proxyDomainName(); + } + + public static TokenModule_DomainNameFactory create() { + return INSTANCE; + } + + public static String proxyDomainName() { + return Preconditions.checkNotNull( + TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java new file mode 100644 index 00000000000..e6628332802 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_ProvideTokenFactory implements Factory { + private final Provider tokenProvider; + + public TokenModule_ProvideTokenFactory(Provider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public Token get() { + return proxyProvideToken(tokenProvider.get()); + } + + public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { + return new TokenModule_ProvideTokenFactory(tokenProvider); + } + + public static Token proxyProvideToken(WebWhoisToken token) { + return Preconditions.checkNotNull( + TokenModule.provideToken(token), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java new file mode 100644 index 00000000000..31710bed6eb --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpClientCodec; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpClientCodecFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = + new WebWhoisModule_ProvideHttpClientCodecFactory(); + + @Override + public HttpClientCodec get() { + return proxyProvideHttpClientCodec(); + } + + public static WebWhoisModule_ProvideHttpClientCodecFactory create() { + return INSTANCE; + } + + public static HttpClientCodec proxyProvideHttpClientCodec() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpClientCodec(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java new file mode 100644 index 00000000000..b69df1a2f7d --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = + new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); + + @Override + public HttpObjectAggregator get() { + return proxyProvideHttpObjectAggregator(); + } + + public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { + return INSTANCE; + } + + public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpObjectAggregator(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java new file mode 100644 index 00000000000..bacebd82f49 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java @@ -0,0 +1,32 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public String get() { + return proxyProvideHttpWhoisHost(module); + } + + public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); + } + + public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { + return Preconditions.checkNotNull( + instance.provideHttpWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..0d098288569 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,54 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final Provider httpWhoisPortProvider; + + private final Provider httpWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpWhoisProtocolFactory( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpWhoisPortProvider = httpWhoisPortProvider; + this.httpWhoisHostProvider = httpWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpWhoisProtocol( + httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( + httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpWhoisProtocol( + int httpWhoisPort, + String httpWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..c40cde16709 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,54 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final Provider httpsWhoisPortProvider; + + private final Provider httpsWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpsWhoisPortProvider = httpsWhoisPortProvider; + this.httpsWhoisHostProvider = httpsWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpsWhoisProtocol( + httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpsWhoisProtocol( + int httpsWhoisPort, + String httpsWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java new file mode 100644 index 00000000000..208d9c7212e --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { + private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = + new WebWhoisModule_ProvideSslProviderFactory(); + + @Override + public SslProvider get() { + return proxyProvideSslProvider(); + } + + public static WebWhoisModule_ProvideSslProviderFactory create() { + return INSTANCE; + } + + public static SslProvider proxyProvideSslProvider() { + return Preconditions.checkNotNull( + WebWhoisModule.provideSslProvider(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..81eb6efc487 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java @@ -0,0 +1,58 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpWhoisHandlerProviders( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..e18a43dd7a8 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java @@ -0,0 +1,75 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider> sslClientInitializerProvider; + + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.sslClientInitializerProvider = sslClientInitializerProvider; + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpsWhoisHandlerProviders( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java new file mode 100644 index 00000000000..39af08b1e60 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java @@ -0,0 +1,154 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { + private final ProberModule proberModule; + + private Provider provideHttpWhoisPortProvider; + + private Provider provideHttpWhoisHostProvider; + + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider provideHttpsWhoisPortProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerProberModule_ProberComponent( + ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { + this.proberModule = proberModuleParam; + initialize(proberModuleParam, webWhoisModuleParam); + } + + public static Builder builder() { + return new Builder(); + } + + public static ProberModule.ProberComponent create() { + return new Builder().build(); + } + + private Set getSetOfProtocol() { + return ImmutableSet.of( + provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); + } + + private WebWhoisToken getWebWhoisToken() { + return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); + } + + @SuppressWarnings("unchecked") + private void initialize( + final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { + this.provideHttpWhoisPortProvider = + ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); + this.provideHttpWhoisHostProvider = + WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + provideHttpWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpWhoisHandlerProvidersProvider)); + this.provideHttpsWhoisPortProvider = + ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + provideHttpsWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public ImmutableMap providePortToProtocolMap() { + return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( + proberModule, getSetOfProtocol()); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); + } + + public static final class Builder { + private ProberModule proberModule; + + private WebWhoisModule webWhoisModule; + + private Builder() {} + + public Builder proberModule(ProberModule proberModule) { + this.proberModule = Preconditions.checkNotNull(proberModule); + return this; + } + + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public ProberModule.ProberComponent build() { + if (proberModule == null) { + this.proberModule = new ProberModule(); + } + if (webWhoisModule == null) { + this.webWhoisModule = new WebWhoisModule(); + } + return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); + } + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java new file mode 100644 index 00000000000..45032a9c7ba --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java @@ -0,0 +1,46 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerTestModule_TestComponent implements TestModule.TestComponent { + private DaggerTestModule_TestComponent() {} + + public static Builder builder() { + return new Builder(); + } + + public static TestModule.TestComponent create() { + return new Builder().build(); + } + + @Override + public ImmutableList> provideHandlers() { + return TestModule_ProvideHandlersFactory.proxyProvideHandlers(TestHandler_Factory.create()); + } + + public static final class Builder { + private Builder() {} + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder testModule(TestModule testModule) { + Preconditions.checkNotNull(testModule); + return this; + } + + public TestModule.TestComponent build() { + return new DaggerTestModule_TestComponent(); + } + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..93f9e4f9f48 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(ProberModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..0aee5faf959 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(ProberModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java new file mode 100644 index 00000000000..7ab2e4e9dd9 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java @@ -0,0 +1,42 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableMap; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvidePortToProtocolMapFactory + implements Factory> { + private final ProberModule module; + + private final Provider> protocolSetProvider; + + public ProberModule_ProvidePortToProtocolMapFactory( + ProberModule module, Provider> protocolSetProvider) { + this.module = module; + this.protocolSetProvider = protocolSetProvider; + } + + @Override + public ImmutableMap get() { + return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); + } + + public static ProberModule_ProvidePortToProtocolMapFactory create( + ProberModule module, Provider> protocolSetProvider) { + return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); + } + + public static ImmutableMap proxyProvidePortToProtocolMap( + ProberModule instance, Set protocolSet) { + return Preconditions.checkNotNull( + instance.providePortToProtocolMap(protocolSet), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java new file mode 100644 index 00000000000..50616d20699 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestHandler_Factory implements Factory { + private static final TestHandler_Factory INSTANCE = new TestHandler_Factory(); + + @Override + public TestHandler get() { + return new TestHandler(); + } + + public static TestHandler_Factory create() { + return INSTANCE; + } + + public static TestHandler newTestHandler() { + return new TestHandler(); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java new file mode 100644 index 00000000000..79e40ee2d4a --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java @@ -0,0 +1,38 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestModule_ProvideHandlersFactory + implements Factory>> { + private final Provider testHandlerProvider; + + public TestModule_ProvideHandlersFactory(Provider testHandlerProvider) { + this.testHandlerProvider = testHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProvideHandlers(testHandlerProvider); + } + + public static TestModule_ProvideHandlersFactory create( + Provider testHandlerProvider) { + return new TestModule_ProvideHandlersFactory(testHandlerProvider); + } + + public static ImmutableList> proxyProvideHandlers( + Provider testHandlerProvider) { + return Preconditions.checkNotNull( + TestModule.provideHandlers(testHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java new file mode 100644 index 00000000000..75b788ec968 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java @@ -0,0 +1,36 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.MembersInjector; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestProtocol_MembersInjector implements MembersInjector { + private final Provider>> + handlerProvidersProvider; + + public TestProtocol_MembersInjector( + Provider>> handlerProvidersProvider) { + this.handlerProvidersProvider = handlerProvidersProvider; + } + + public static MembersInjector create( + Provider>> handlerProvidersProvider) { + return new TestProtocol_MembersInjector(handlerProvidersProvider); + } + + @Override + public void injectMembers(TestProtocol instance) { + injectTestProtocolHandlers(instance, handlerProvidersProvider.get()); + } + + public static void injectTestProtocolHandlers( + TestProtocol instance, ImmutableList> handlerProviders) { + instance.TestProtocolHandlers(handlerProviders); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java new file mode 100644 index 00000000000..1dc41bf0e16 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_DomainNameFactory implements Factory { + private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); + + @Override + public String get() { + return proxyDomainName(); + } + + public static TokenModule_DomainNameFactory create() { + return INSTANCE; + } + + public static String proxyDomainName() { + return Preconditions.checkNotNull( + TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java new file mode 100644 index 00000000000..afc66775c9d --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_ProvideTokenFactory implements Factory { + private final Provider tokenProvider; + + public TokenModule_ProvideTokenFactory(Provider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public Token get() { + return proxyProvideToken(tokenProvider.get()); + } + + public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { + return new TokenModule_ProvideTokenFactory(tokenProvider); + } + + public static Token proxyProvideToken(WebWhoisToken token) { + return Preconditions.checkNotNull( + TokenModule.provideToken(token), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java new file mode 100644 index 00000000000..7c756174314 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpClientCodec; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpClientCodecFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = + new WebWhoisModule_ProvideHttpClientCodecFactory(); + + @Override + public HttpClientCodec get() { + return proxyProvideHttpClientCodec(); + } + + public static WebWhoisModule_ProvideHttpClientCodecFactory create() { + return INSTANCE; + } + + public static HttpClientCodec proxyProvideHttpClientCodec() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpClientCodec(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java new file mode 100644 index 00000000000..20785cde372 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = + new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); + + @Override + public HttpObjectAggregator get() { + return proxyProvideHttpObjectAggregator(); + } + + public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { + return INSTANCE; + } + + public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpObjectAggregator(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java new file mode 100644 index 00000000000..7087ab940bc --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java @@ -0,0 +1,32 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public String get() { + return proxyProvideHttpWhoisHost(module); + } + + public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); + } + + public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { + return Preconditions.checkNotNull( + instance.provideHttpWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..ed7e62f3a5f --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final Provider httpWhoisPortProvider; + + private final Provider httpWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpWhoisProtocolFactory( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpWhoisPortProvider = httpWhoisPortProvider; + this.httpWhoisHostProvider = httpWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpWhoisProtocol( + httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( + httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpWhoisProtocol( + int httpWhoisPort, + String httpWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..4ab50681eea --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final Provider httpsWhoisPortProvider; + + private final Provider httpsWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpsWhoisPortProvider = httpsWhoisPortProvider; + this.httpsWhoisHostProvider = httpsWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpsWhoisProtocol( + httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpsWhoisProtocol( + int httpsWhoisPort, + String httpsWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java new file mode 100644 index 00000000000..7579cc752cf --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { + private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = + new WebWhoisModule_ProvideSslProviderFactory(); + + @Override + public SslProvider get() { + return proxyProvideSslProvider(); + } + + public static WebWhoisModule_ProvideSslProviderFactory create() { + return INSTANCE; + } + + public static SslProvider proxyProvideSslProvider() { + return Preconditions.checkNotNull( + WebWhoisModule.provideSslProvider(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..37431babcb9 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java @@ -0,0 +1,58 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpWhoisHandlerProviders( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..adf393894e8 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java @@ -0,0 +1,75 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider> sslClientInitializerProvider; + + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.sslClientInitializerProvider = sslClientInitializerProvider; + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpsWhoisHandlerProviders( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} From 9558790481f299c3e3db336216d0f5074c9cf3a8 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:29:25 -0400 Subject: [PATCH 079/337] Removed all generated java --- .../blackbox/ActionHandler_Factory.java | 25 --- .../DaggerProberModule_ProberComponent.java | 154 ----------------- ...aggerWebWhoisModule_WebWhoisComponent.java | 119 -------------- ...berModule_ProvideHttpWhoIsPortFactory.java | 29 ---- ...berModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 29 ---- ...erModule_ProvideHttpsWhoIsPortFactory.java | 29 ---- ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...dule_ProvideHttpsWhoisProtocolFactory.java | 29 ---- ...odule_ProvidePortToProtocolMapFactory.java | 42 ----- .../blackbox/ProbingStepWeb_Factory.java | 30 ---- .../blackbox/ProbingStep_Factory.java | 27 --- .../blackbox/TestToken_Factory.java | 45 ----- .../blackbox/TestToken_MembersInjector.java | 30 ---- .../TokenModule_DomainNameFactory.java | 27 --- .../TokenModule_ProvideTokenFactory.java | 35 ---- .../blackbox/Token_MembersInjector.java | 31 ---- .../Tokens/WebWhoisToken_Factory.java | 25 --- .../WebWhoisModule_HttpWhoisHostFactory.java | 28 ---- .../WebWhoisModule_HttpWhoisPathFactory.java | 28 ---- .../WebWhoisModule_HttpWhoisPortFactory.java | 26 --- .../WebWhoisModule_HttpsWhoisHostFactory.java | 29 ---- .../WebWhoisModule_HttpsWhoisPathFactory.java | 29 ---- .../WebWhoisModule_HttpsWhoisPortFactory.java | 26 --- ...sModule_ProvideHttpClientCodecFactory.java | 31 ---- ...le_ProvideHttpObjectAggregatorFactory.java | 31 ---- ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ---- ...oisModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ------ ...isModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ------ ...WhoisModule_ProvideSslProviderFactory.java | 30 ---- ...viderHttpWhoisHandlerProvidersFactory.java | 58 ------- ...iderHttpsWhoisHandlerProvidersFactory.java | 75 --------- .../blackbox/WebWhoisToken_Factory.java | 25 --- .../handlers/ActionHandler_Factory.java | 25 --- .../handlers/RedirectHandler_Factory.java | 25 --- .../SslClientInitializer_Factory.java | 35 ---- .../handlers/WebWhoIsHandler_Factory.java | 25 --- .../WebWhoisActionHandler_Factory.java | 25 --- .../DaggerProberModule_ProberComponent.java | 155 ------------------ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...odule_ProvidePortToProtocolMapFactory.java | 43 ----- .../TokenModule_DomainNameFactory.java | 27 --- .../TokenModule_ProvideTokenFactory.java | 35 ---- ...sModule_ProvideHttpClientCodecFactory.java | 31 ---- ...le_ProvideHttpObjectAggregatorFactory.java | 31 ---- ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 54 ------ ...dule_ProvideHttpsWhoisProtocolFactory.java | 54 ------ ...WhoisModule_ProvideSslProviderFactory.java | 30 ---- ...viderHttpWhoisHandlerProvidersFactory.java | 58 ------- ...iderHttpsWhoisHandlerProvidersFactory.java | 75 --------- .../DaggerProberModule_ProberComponent.java | 154 ----------------- .../DaggerTestModule_TestComponent.java | 46 ------ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...odule_ProvidePortToProtocolMapFactory.java | 42 ----- .../blackbox/TestHandler_Factory.java | 25 --- .../TestModule_ProvideHandlersFactory.java | 38 ----- .../TestProtocol_MembersInjector.java | 36 ---- .../TokenModule_DomainNameFactory.java | 27 --- .../TokenModule_ProvideTokenFactory.java | 35 ---- ...sModule_ProvideHttpClientCodecFactory.java | 31 ---- ...le_ProvideHttpObjectAggregatorFactory.java | 31 ---- ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ------ ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ------ ...WhoisModule_ProvideSslProviderFactory.java | 30 ---- ...viderHttpWhoisHandlerProvidersFactory.java | 58 ------- ...iderHttpsWhoisHandlerProvidersFactory.java | 75 --------- 72 files changed, 3018 deletions(-) delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java deleted file mode 100644 index 8a727c63bbb..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ActionHandler_Factory implements Factory { - private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); - - @Override - public ActionHandler get() { - return new ActionHandler(); - } - - public static ActionHandler_Factory create() { - return INSTANCE; - } - - public static ActionHandler newActionHandler() { - return new ActionHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java deleted file mode 100644 index 39af08b1e60..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java +++ /dev/null @@ -1,154 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { - private final ProberModule proberModule; - - private Provider provideHttpWhoisPortProvider; - - private Provider provideHttpWhoisHostProvider; - - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider provideHttpsWhoisPortProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerProberModule_ProberComponent( - ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { - this.proberModule = proberModuleParam; - initialize(proberModuleParam, webWhoisModuleParam); - } - - public static Builder builder() { - return new Builder(); - } - - public static ProberModule.ProberComponent create() { - return new Builder().build(); - } - - private Set getSetOfProtocol() { - return ImmutableSet.of( - provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); - } - - private WebWhoisToken getWebWhoisToken() { - return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); - } - - @SuppressWarnings("unchecked") - private void initialize( - final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { - this.provideHttpWhoisPortProvider = - ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); - this.provideHttpWhoisHostProvider = - WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - provideHttpWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpWhoisHandlerProvidersProvider)); - this.provideHttpsWhoisPortProvider = - ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - provideHttpsWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public ImmutableMap providePortToProtocolMap() { - return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( - proberModule, getSetOfProtocol()); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); - } - - public static final class Builder { - private ProberModule proberModule; - - private WebWhoisModule webWhoisModule; - - private Builder() {} - - public Builder proberModule(ProberModule proberModule) { - this.proberModule = Preconditions.checkNotNull(proberModule); - return this; - } - - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public ProberModule.ProberComponent build() { - if (proberModule == null) { - this.proberModule = new ProberModule(); - } - if (webWhoisModule == null) { - this.webWhoisModule = new WebWhoisModule(); - } - return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); - } - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java deleted file mode 100644 index ba272c4730a..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java +++ /dev/null @@ -1,119 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerWebWhoisModule_WebWhoisComponent - implements WebWhoisModule.WebWhoisComponent { - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerWebWhoisModule_WebWhoisComponent() { - - initialize(); - } - - public static Builder builder() { - return new Builder(); - } - - public static WebWhoisModule.WebWhoisComponent create() { - return new Builder().build(); - } - - @SuppressWarnings("unchecked") - private void initialize() { - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - WebWhoisModule_HttpWhoisPortFactory.create(), - WebWhoisModule_HttpWhoisHostFactory.create(), - providerHttpWhoisHandlerProvidersProvider)); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - WebWhoisModule_HttpsWhoisPortFactory.create(), - WebWhoisModule_HttpsWhoisHostFactory.create(), - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public Protocol provideHttpWhoisProtocol() { - return provideHttpWhoisProtocolProvider.get(); - } - - @Override - public Protocol provideHttpsWhoisProtocol() { - return provideHttpsWhoisProtocolProvider.get(); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(); - } - - public static final class Builder { - private Builder() {} - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public WebWhoisModule.WebWhoisComponent build() { - return new DaggerWebWhoisModule_WebWhoisComponent(); - } - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java deleted file mode 100644 index 659d36c8249..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoIsPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoIsPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoIsPort(module); - } - - public static ProberModule_ProvideHttpWhoIsPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoIsPortFactory(module); - } - - public static int proxyProvideHttpWhoIsPort(ProberModule instance) { - return instance.provideHttpWhoIsPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index 93f9e4f9f48..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(ProberModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index 4d560ae3c94..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisProtocolFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisProtocol(module); - } - - public static ProberModule_ProvideHttpWhoisProtocolFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisProtocolFactory(module); - } - - public static int proxyProvideHttpWhoisProtocol(ProberModule instance) { - return instance.provideHttpWhoisProtocol(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java deleted file mode 100644 index a49efddd550..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoIsPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoIsPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoIsPort(module); - } - - public static ProberModule_ProvideHttpsWhoIsPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoIsPortFactory(module); - } - - public static int proxyProvideHttpsWhoIsPort(ProberModule instance) { - return instance.provideHttpsWhoIsPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index 0aee5faf959..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(ProberModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index faaae10cb72..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisProtocolFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisProtocol(module); - } - - public static ProberModule_ProvideHttpsWhoisProtocolFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisProtocolFactory(module); - } - - public static int proxyProvideHttpsWhoisProtocol(ProberModule instance) { - return instance.provideHttpsWhoisProtocol(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java deleted file mode 100644 index 7ab2e4e9dd9..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableMap; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvidePortToProtocolMapFactory - implements Factory> { - private final ProberModule module; - - private final Provider> protocolSetProvider; - - public ProberModule_ProvidePortToProtocolMapFactory( - ProberModule module, Provider> protocolSetProvider) { - this.module = module; - this.protocolSetProvider = protocolSetProvider; - } - - @Override - public ImmutableMap get() { - return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); - } - - public static ProberModule_ProvidePortToProtocolMapFactory create( - ProberModule module, Provider> protocolSetProvider) { - return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); - } - - public static ImmutableMap proxyProvidePortToProtocolMap( - ProberModule instance, Set protocolSet) { - return Preconditions.checkNotNull( - instance.providePortToProtocolMap(protocolSet), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java deleted file mode 100644 index a8d428b93c2..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProbingStepWeb_Factory implements Factory { - private final Provider protocolProvider; - - public ProbingStepWeb_Factory(Provider protocolProvider) { - this.protocolProvider = protocolProvider; - } - - @Override - public ProbingStepWeb get() { - return new ProbingStepWeb(protocolProvider.get()); - } - - public static ProbingStepWeb_Factory create(Provider protocolProvider) { - return new ProbingStepWeb_Factory(protocolProvider); - } - - public static ProbingStepWeb newProbingStepWeb(Protocol protocol) { - return new ProbingStepWeb(protocol); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java deleted file mode 100644 index 1e8ba7f6af6..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProbingStep_Factory implements Factory> { - @SuppressWarnings("rawtypes") - private static final ProbingStep_Factory INSTANCE = new ProbingStep_Factory(); - - @Override - public ProbingStep get() { - return new ProbingStep(); - } - - @SuppressWarnings("unchecked") - public static ProbingStep_Factory create() { - return INSTANCE; - } - - public static ProbingStep newProbingStep() { - return new ProbingStep(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java deleted file mode 100644 index fd4bf43308d..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java +++ /dev/null @@ -1,45 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestToken_Factory implements Factory { - private final Provider actionHandlerProvider; - - private final Provider domainNameProvider; - - private final Provider protocolProvider; - - public TestToken_Factory( - Provider actionHandlerProvider, - Provider domainNameProvider, - Provider protocolProvider) { - this.actionHandlerProvider = actionHandlerProvider; - this.domainNameProvider = domainNameProvider; - this.protocolProvider = protocolProvider; - } - - @Override - public TestToken get() { - TestToken instance = new TestToken(actionHandlerProvider.get(), domainNameProvider.get()); - TestToken_MembersInjector.injectProtocol(instance, protocolProvider.get()); - return instance; - } - - public static TestToken_Factory create( - Provider actionHandlerProvider, - Provider domainNameProvider, - Provider protocolProvider) { - return new TestToken_Factory(actionHandlerProvider, domainNameProvider, protocolProvider); - } - - public static TestToken newTestToken(ActionHandler actionHandler, String domainName) { - return new TestToken(actionHandler, domainName); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java deleted file mode 100644 index db846ba4a36..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.MembersInjector; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestToken_MembersInjector implements MembersInjector { - private final Provider protocolProvider; - - public TestToken_MembersInjector(Provider protocolProvider) { - this.protocolProvider = protocolProvider; - } - - public static MembersInjector create(Provider protocolProvider) { - return new TestToken_MembersInjector(protocolProvider); - } - - @Override - public void injectMembers(TestToken instance) { - injectProtocol(instance, protocolProvider.get()); - } - - public static void injectProtocol(TestToken instance, Protocol protocol) { - instance.protocol = protocol; - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java deleted file mode 100644 index 1dc41bf0e16..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_DomainNameFactory implements Factory { - private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); - - @Override - public String get() { - return proxyDomainName(); - } - - public static TokenModule_DomainNameFactory create() { - return INSTANCE; - } - - public static String proxyDomainName() { - return Preconditions.checkNotNull( - TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java deleted file mode 100644 index afc66775c9d..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_ProvideTokenFactory implements Factory { - private final Provider tokenProvider; - - public TokenModule_ProvideTokenFactory(Provider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - @Override - public Token get() { - return proxyProvideToken(tokenProvider.get()); - } - - public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { - return new TokenModule_ProvideTokenFactory(tokenProvider); - } - - public static Token proxyProvideToken(WebWhoisToken token) { - return Preconditions.checkNotNull( - TokenModule.provideToken(token), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java deleted file mode 100644 index feab7f7d227..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.MembersInjector; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class Token_MembersInjector implements MembersInjector { - private final Provider actionHandlerProvider; - - public Token_MembersInjector(Provider actionHandlerProvider) { - this.actionHandlerProvider = actionHandlerProvider; - } - - public static MembersInjector create(Provider actionHandlerProvider) { - return new Token_MembersInjector(actionHandlerProvider); - } - - @Override - public void injectMembers(Token instance) { - injectActionHandler(instance, actionHandlerProvider.get()); - } - - public static void injectActionHandler(Object instance, ActionHandler actionHandler) { - ((Token) instance).actionHandler = actionHandler; - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java deleted file mode 100644 index 3d153c08fdb..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.Tokens; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisToken_Factory implements Factory { - private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); - - @Override - public WebWhoisToken get() { - return new WebWhoisToken(); - } - - public static WebWhoisToken_Factory create() { - return INSTANCE; - } - - public static WebWhoisToken newWebWhoisToken() { - return new WebWhoisToken(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java deleted file mode 100644 index f2f34a674d3..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpWhoisHostFactory implements Factory { - private static final WebWhoisModule_HttpWhoisHostFactory INSTANCE = - new WebWhoisModule_HttpWhoisHostFactory(); - - @Override - public String get() { - return proxyHttpWhoisHost(); - } - - public static WebWhoisModule_HttpWhoisHostFactory create() { - return INSTANCE; - } - - public static String proxyHttpWhoisHost() { - return Preconditions.checkNotNull( - WebWhoisModule.httpWhoisHost(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java deleted file mode 100644 index 67ab24c06fd..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpWhoisPathFactory implements Factory { - private static final WebWhoisModule_HttpWhoisPathFactory INSTANCE = - new WebWhoisModule_HttpWhoisPathFactory(); - - @Override - public String get() { - return proxyHttpWhoisPath(); - } - - public static WebWhoisModule_HttpWhoisPathFactory create() { - return INSTANCE; - } - - public static String proxyHttpWhoisPath() { - return Preconditions.checkNotNull( - WebWhoisModule.httpWhoisPath(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java deleted file mode 100644 index 4a29a990b67..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpWhoisPortFactory implements Factory { - private static final WebWhoisModule_HttpWhoisPortFactory INSTANCE = - new WebWhoisModule_HttpWhoisPortFactory(); - - @Override - public Integer get() { - return proxyHttpWhoisPort(); - } - - public static WebWhoisModule_HttpWhoisPortFactory create() { - return INSTANCE; - } - - public static int proxyHttpWhoisPort() { - return WebWhoisModule.httpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java deleted file mode 100644 index f8a7fae07a8..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpsWhoisHostFactory implements Factory { - private static final WebWhoisModule_HttpsWhoisHostFactory INSTANCE = - new WebWhoisModule_HttpsWhoisHostFactory(); - - @Override - public String get() { - return proxyHttpsWhoisHost(); - } - - public static WebWhoisModule_HttpsWhoisHostFactory create() { - return INSTANCE; - } - - public static String proxyHttpsWhoisHost() { - return Preconditions.checkNotNull( - WebWhoisModule.httpsWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java deleted file mode 100644 index 4cabb7b5384..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpsWhoisPathFactory implements Factory { - private static final WebWhoisModule_HttpsWhoisPathFactory INSTANCE = - new WebWhoisModule_HttpsWhoisPathFactory(); - - @Override - public String get() { - return proxyHttpsWhoisPath(); - } - - public static WebWhoisModule_HttpsWhoisPathFactory create() { - return INSTANCE; - } - - public static String proxyHttpsWhoisPath() { - return Preconditions.checkNotNull( - WebWhoisModule.httpsWhoisPath(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java deleted file mode 100644 index 30f4564213a..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpsWhoisPortFactory implements Factory { - private static final WebWhoisModule_HttpsWhoisPortFactory INSTANCE = - new WebWhoisModule_HttpsWhoisPortFactory(); - - @Override - public Integer get() { - return proxyHttpsWhoisPort(); - } - - public static WebWhoisModule_HttpsWhoisPortFactory create() { - return INSTANCE; - } - - public static int proxyHttpsWhoisPort() { - return WebWhoisModule.httpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java deleted file mode 100644 index 7c756174314..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpClientCodec; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpClientCodecFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = - new WebWhoisModule_ProvideHttpClientCodecFactory(); - - @Override - public HttpClientCodec get() { - return proxyProvideHttpClientCodec(); - } - - public static WebWhoisModule_ProvideHttpClientCodecFactory create() { - return INSTANCE; - } - - public static HttpClientCodec proxyProvideHttpClientCodec() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpClientCodec(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java deleted file mode 100644 index 20785cde372..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = - new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); - - @Override - public HttpObjectAggregator get() { - return proxyProvideHttpObjectAggregator(); - } - - public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { - return INSTANCE; - } - - public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpObjectAggregator(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java deleted file mode 100644 index 7087ab940bc..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public String get() { - return proxyProvideHttpWhoisHost(module); - } - - public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); - } - - public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { - return Preconditions.checkNotNull( - instance.provideHttpWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index a4aaf24978e..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisPortFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisPortFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static WebWhoisModule_ProvideHttpWhoisPortFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(WebWhoisModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index ed7e62f3a5f..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final Provider httpWhoisPortProvider; - - private final Provider httpWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpWhoisProtocolFactory( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpWhoisPortProvider = httpWhoisPortProvider; - this.httpWhoisHostProvider = httpWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpWhoisProtocol( - httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( - httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpWhoisProtocol( - int httpWhoisPort, - String httpWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index c3d7c6546e5..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisPortFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpsWhoisPortFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static WebWhoisModule_ProvideHttpsWhoisPortFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(WebWhoisModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index 4ab50681eea..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final Provider httpsWhoisPortProvider; - - private final Provider httpsWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpsWhoisPortProvider = httpsWhoisPortProvider; - this.httpsWhoisHostProvider = httpsWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpsWhoisProtocol( - httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpsWhoisProtocol( - int httpsWhoisPort, - String httpsWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java deleted file mode 100644 index 7579cc752cf..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { - private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = - new WebWhoisModule_ProvideSslProviderFactory(); - - @Override - public SslProvider get() { - return proxyProvideSslProvider(); - } - - public static WebWhoisModule_ProvideSslProviderFactory create() { - return INSTANCE; - } - - public static SslProvider proxyProvideSslProvider() { - return Preconditions.checkNotNull( - WebWhoisModule.provideSslProvider(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java deleted file mode 100644 index 37431babcb9..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpWhoisHandlerProviders( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java deleted file mode 100644 index adf393894e8..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider> sslClientInitializerProvider; - - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.sslClientInitializerProvider = sslClientInitializerProvider; - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpsWhoisHandlerProviders( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java deleted file mode 100644 index 6c840214a11..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisToken_Factory implements Factory { - private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); - - @Override - public WebWhoisToken get() { - return new WebWhoisToken(); - } - - public static WebWhoisToken_Factory create() { - return INSTANCE; - } - - public static WebWhoisToken newWebWhoisToken() { - return new WebWhoisToken(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java deleted file mode 100644 index d94df8b392f..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ActionHandler_Factory implements Factory { - private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); - - @Override - public ActionHandler get() { - return new ActionHandler(); - } - - public static ActionHandler_Factory create() { - return INSTANCE; - } - - public static ActionHandler newActionHandler() { - return new ActionHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java deleted file mode 100644 index ddf10cf830b..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class RedirectHandler_Factory implements Factory { - private static final RedirectHandler_Factory INSTANCE = new RedirectHandler_Factory(); - - @Override - public RedirectHandler get() { - return new RedirectHandler(); - } - - public static RedirectHandler_Factory create() { - return INSTANCE; - } - - public static RedirectHandler newRedirectHandler() { - return new RedirectHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java deleted file mode 100644 index 7fa480f418e..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import io.netty.channel.Channel; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class SslClientInitializer_Factory - implements Factory> { - private final Provider sslProvider; - - public SslClientInitializer_Factory(Provider sslProvider) { - this.sslProvider = sslProvider; - } - - @Override - public SslClientInitializer get() { - return new SslClientInitializer(sslProvider.get()); - } - - public static SslClientInitializer_Factory create( - Provider sslProvider) { - return new SslClientInitializer_Factory(sslProvider); - } - - public static SslClientInitializer newSslClientInitializer( - SslProvider sslProvider) { - return new SslClientInitializer(sslProvider); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java deleted file mode 100644 index 26b68fdc09c..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoIsHandler_Factory implements Factory { - private static final WebWhoIsHandler_Factory INSTANCE = new WebWhoIsHandler_Factory(); - - @Override - public WebWhoIsHandler get() { - return new WebWhoIsHandler(); - } - - public static WebWhoIsHandler_Factory create() { - return INSTANCE; - } - - public static WebWhoIsHandler newWebWhoIsHandler() { - return new WebWhoIsHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java deleted file mode 100644 index dc008e1a724..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisActionHandler_Factory implements Factory { - private static final WebWhoisActionHandler_Factory INSTANCE = new WebWhoisActionHandler_Factory(); - - @Override - public WebWhoisActionHandler get() { - return new WebWhoisActionHandler(); - } - - public static WebWhoisActionHandler_Factory create() { - return INSTANCE; - } - - public static WebWhoisActionHandler newWebWhoisActionHandler() { - return new WebWhoisActionHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java deleted file mode 100644 index b7971395941..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java +++ /dev/null @@ -1,155 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { - private final ProberModule proberModule; - - private Provider provideHttpWhoisPortProvider; - - private Provider provideHttpWhoisHostProvider; - - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider provideHttpsWhoisPortProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerProberModule_ProberComponent( - ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { - this.proberModule = proberModuleParam; - initialize(proberModuleParam, webWhoisModuleParam); - } - - public static Builder builder() { - return new Builder(); - } - - public static ProberModule.ProberComponent create() { - return new Builder().build(); - } - - private Set getSetOfProtocol() { - return ImmutableSet.of( - provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); - } - - private WebWhoisToken getWebWhoisToken() { - return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); - } - - @SuppressWarnings("unchecked") - private void initialize( - final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { - this.provideHttpWhoisPortProvider = - ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); - this.provideHttpWhoisHostProvider = - WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - provideHttpWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpWhoisHandlerProvidersProvider)); - this.provideHttpsWhoisPortProvider = - ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - provideHttpsWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public ImmutableMap providePortToProtocolMap() { - return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( - proberModule, getSetOfProtocol()); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); - } - - public static final class Builder { - private ProberModule proberModule; - - private WebWhoisModule webWhoisModule; - - private Builder() {} - - public Builder proberModule(ProberModule proberModule) { - this.proberModule = Preconditions.checkNotNull(proberModule); - return this; - } - - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public ProberModule.ProberComponent build() { - if (proberModule == null) { - this.proberModule = new ProberModule(); - } - if (webWhoisModule == null) { - this.webWhoisModule = new WebWhoisModule(); - } - return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); - } - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index 955698498db..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(ProberModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index 0b97c8dbb72..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(ProberModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java deleted file mode 100644 index e0597aa25f5..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableMap; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvidePortToProtocolMapFactory - implements Factory> { - private final ProberModule module; - - private final Provider> protocolSetProvider; - - public ProberModule_ProvidePortToProtocolMapFactory( - ProberModule module, Provider> protocolSetProvider) { - this.module = module; - this.protocolSetProvider = protocolSetProvider; - } - - @Override - public ImmutableMap get() { - return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); - } - - public static ProberModule_ProvidePortToProtocolMapFactory create( - ProberModule module, Provider> protocolSetProvider) { - return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); - } - - public static ImmutableMap proxyProvidePortToProtocolMap( - ProberModule instance, Set protocolSet) { - return Preconditions.checkNotNull( - instance.providePortToProtocolMap(protocolSet), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java deleted file mode 100644 index 20e2ca11502..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_DomainNameFactory implements Factory { - private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); - - @Override - public String get() { - return proxyDomainName(); - } - - public static TokenModule_DomainNameFactory create() { - return INSTANCE; - } - - public static String proxyDomainName() { - return Preconditions.checkNotNull( - TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java deleted file mode 100644 index e6628332802..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_ProvideTokenFactory implements Factory { - private final Provider tokenProvider; - - public TokenModule_ProvideTokenFactory(Provider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - @Override - public Token get() { - return proxyProvideToken(tokenProvider.get()); - } - - public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { - return new TokenModule_ProvideTokenFactory(tokenProvider); - } - - public static Token proxyProvideToken(WebWhoisToken token) { - return Preconditions.checkNotNull( - TokenModule.provideToken(token), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java deleted file mode 100644 index 31710bed6eb..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpClientCodec; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpClientCodecFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = - new WebWhoisModule_ProvideHttpClientCodecFactory(); - - @Override - public HttpClientCodec get() { - return proxyProvideHttpClientCodec(); - } - - public static WebWhoisModule_ProvideHttpClientCodecFactory create() { - return INSTANCE; - } - - public static HttpClientCodec proxyProvideHttpClientCodec() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpClientCodec(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java deleted file mode 100644 index b69df1a2f7d..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = - new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); - - @Override - public HttpObjectAggregator get() { - return proxyProvideHttpObjectAggregator(); - } - - public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { - return INSTANCE; - } - - public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpObjectAggregator(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java deleted file mode 100644 index bacebd82f49..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public String get() { - return proxyProvideHttpWhoisHost(module); - } - - public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); - } - - public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { - return Preconditions.checkNotNull( - instance.provideHttpWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index 0d098288569..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final Provider httpWhoisPortProvider; - - private final Provider httpWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpWhoisProtocolFactory( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpWhoisPortProvider = httpWhoisPortProvider; - this.httpWhoisHostProvider = httpWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpWhoisProtocol( - httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( - httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpWhoisProtocol( - int httpWhoisPort, - String httpWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index c40cde16709..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final Provider httpsWhoisPortProvider; - - private final Provider httpsWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpsWhoisPortProvider = httpsWhoisPortProvider; - this.httpsWhoisHostProvider = httpsWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpsWhoisProtocol( - httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpsWhoisProtocol( - int httpsWhoisPort, - String httpsWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java deleted file mode 100644 index 208d9c7212e..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { - private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = - new WebWhoisModule_ProvideSslProviderFactory(); - - @Override - public SslProvider get() { - return proxyProvideSslProvider(); - } - - public static WebWhoisModule_ProvideSslProviderFactory create() { - return INSTANCE; - } - - public static SslProvider proxyProvideSslProvider() { - return Preconditions.checkNotNull( - WebWhoisModule.provideSslProvider(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java deleted file mode 100644 index 81eb6efc487..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpWhoisHandlerProviders( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java deleted file mode 100644 index e18a43dd7a8..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider> sslClientInitializerProvider; - - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.sslClientInitializerProvider = sslClientInitializerProvider; - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpsWhoisHandlerProviders( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java deleted file mode 100644 index 39af08b1e60..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java +++ /dev/null @@ -1,154 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { - private final ProberModule proberModule; - - private Provider provideHttpWhoisPortProvider; - - private Provider provideHttpWhoisHostProvider; - - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider provideHttpsWhoisPortProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerProberModule_ProberComponent( - ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { - this.proberModule = proberModuleParam; - initialize(proberModuleParam, webWhoisModuleParam); - } - - public static Builder builder() { - return new Builder(); - } - - public static ProberModule.ProberComponent create() { - return new Builder().build(); - } - - private Set getSetOfProtocol() { - return ImmutableSet.of( - provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); - } - - private WebWhoisToken getWebWhoisToken() { - return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); - } - - @SuppressWarnings("unchecked") - private void initialize( - final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { - this.provideHttpWhoisPortProvider = - ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); - this.provideHttpWhoisHostProvider = - WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - provideHttpWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpWhoisHandlerProvidersProvider)); - this.provideHttpsWhoisPortProvider = - ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - provideHttpsWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public ImmutableMap providePortToProtocolMap() { - return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( - proberModule, getSetOfProtocol()); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); - } - - public static final class Builder { - private ProberModule proberModule; - - private WebWhoisModule webWhoisModule; - - private Builder() {} - - public Builder proberModule(ProberModule proberModule) { - this.proberModule = Preconditions.checkNotNull(proberModule); - return this; - } - - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public ProberModule.ProberComponent build() { - if (proberModule == null) { - this.proberModule = new ProberModule(); - } - if (webWhoisModule == null) { - this.webWhoisModule = new WebWhoisModule(); - } - return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); - } - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java deleted file mode 100644 index 45032a9c7ba..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java +++ /dev/null @@ -1,46 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerTestModule_TestComponent implements TestModule.TestComponent { - private DaggerTestModule_TestComponent() {} - - public static Builder builder() { - return new Builder(); - } - - public static TestModule.TestComponent create() { - return new Builder().build(); - } - - @Override - public ImmutableList> provideHandlers() { - return TestModule_ProvideHandlersFactory.proxyProvideHandlers(TestHandler_Factory.create()); - } - - public static final class Builder { - private Builder() {} - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder testModule(TestModule testModule) { - Preconditions.checkNotNull(testModule); - return this; - } - - public TestModule.TestComponent build() { - return new DaggerTestModule_TestComponent(); - } - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index 93f9e4f9f48..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(ProberModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index 0aee5faf959..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(ProberModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java deleted file mode 100644 index 7ab2e4e9dd9..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableMap; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvidePortToProtocolMapFactory - implements Factory> { - private final ProberModule module; - - private final Provider> protocolSetProvider; - - public ProberModule_ProvidePortToProtocolMapFactory( - ProberModule module, Provider> protocolSetProvider) { - this.module = module; - this.protocolSetProvider = protocolSetProvider; - } - - @Override - public ImmutableMap get() { - return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); - } - - public static ProberModule_ProvidePortToProtocolMapFactory create( - ProberModule module, Provider> protocolSetProvider) { - return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); - } - - public static ImmutableMap proxyProvidePortToProtocolMap( - ProberModule instance, Set protocolSet) { - return Preconditions.checkNotNull( - instance.providePortToProtocolMap(protocolSet), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java deleted file mode 100644 index 50616d20699..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestHandler_Factory implements Factory { - private static final TestHandler_Factory INSTANCE = new TestHandler_Factory(); - - @Override - public TestHandler get() { - return new TestHandler(); - } - - public static TestHandler_Factory create() { - return INSTANCE; - } - - public static TestHandler newTestHandler() { - return new TestHandler(); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java deleted file mode 100644 index 79e40ee2d4a..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestModule_ProvideHandlersFactory - implements Factory>> { - private final Provider testHandlerProvider; - - public TestModule_ProvideHandlersFactory(Provider testHandlerProvider) { - this.testHandlerProvider = testHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProvideHandlers(testHandlerProvider); - } - - public static TestModule_ProvideHandlersFactory create( - Provider testHandlerProvider) { - return new TestModule_ProvideHandlersFactory(testHandlerProvider); - } - - public static ImmutableList> proxyProvideHandlers( - Provider testHandlerProvider) { - return Preconditions.checkNotNull( - TestModule.provideHandlers(testHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java deleted file mode 100644 index 75b788ec968..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java +++ /dev/null @@ -1,36 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.MembersInjector; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestProtocol_MembersInjector implements MembersInjector { - private final Provider>> - handlerProvidersProvider; - - public TestProtocol_MembersInjector( - Provider>> handlerProvidersProvider) { - this.handlerProvidersProvider = handlerProvidersProvider; - } - - public static MembersInjector create( - Provider>> handlerProvidersProvider) { - return new TestProtocol_MembersInjector(handlerProvidersProvider); - } - - @Override - public void injectMembers(TestProtocol instance) { - injectTestProtocolHandlers(instance, handlerProvidersProvider.get()); - } - - public static void injectTestProtocolHandlers( - TestProtocol instance, ImmutableList> handlerProviders) { - instance.TestProtocolHandlers(handlerProviders); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java deleted file mode 100644 index 1dc41bf0e16..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_DomainNameFactory implements Factory { - private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); - - @Override - public String get() { - return proxyDomainName(); - } - - public static TokenModule_DomainNameFactory create() { - return INSTANCE; - } - - public static String proxyDomainName() { - return Preconditions.checkNotNull( - TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java deleted file mode 100644 index afc66775c9d..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_ProvideTokenFactory implements Factory { - private final Provider tokenProvider; - - public TokenModule_ProvideTokenFactory(Provider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - @Override - public Token get() { - return proxyProvideToken(tokenProvider.get()); - } - - public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { - return new TokenModule_ProvideTokenFactory(tokenProvider); - } - - public static Token proxyProvideToken(WebWhoisToken token) { - return Preconditions.checkNotNull( - TokenModule.provideToken(token), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java deleted file mode 100644 index 7c756174314..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpClientCodec; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpClientCodecFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = - new WebWhoisModule_ProvideHttpClientCodecFactory(); - - @Override - public HttpClientCodec get() { - return proxyProvideHttpClientCodec(); - } - - public static WebWhoisModule_ProvideHttpClientCodecFactory create() { - return INSTANCE; - } - - public static HttpClientCodec proxyProvideHttpClientCodec() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpClientCodec(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java deleted file mode 100644 index 20785cde372..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = - new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); - - @Override - public HttpObjectAggregator get() { - return proxyProvideHttpObjectAggregator(); - } - - public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { - return INSTANCE; - } - - public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpObjectAggregator(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java deleted file mode 100644 index 7087ab940bc..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public String get() { - return proxyProvideHttpWhoisHost(module); - } - - public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); - } - - public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { - return Preconditions.checkNotNull( - instance.provideHttpWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index ed7e62f3a5f..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final Provider httpWhoisPortProvider; - - private final Provider httpWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpWhoisProtocolFactory( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpWhoisPortProvider = httpWhoisPortProvider; - this.httpWhoisHostProvider = httpWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpWhoisProtocol( - httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( - httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpWhoisProtocol( - int httpWhoisPort, - String httpWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index 4ab50681eea..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final Provider httpsWhoisPortProvider; - - private final Provider httpsWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpsWhoisPortProvider = httpsWhoisPortProvider; - this.httpsWhoisHostProvider = httpsWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpsWhoisProtocol( - httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpsWhoisProtocol( - int httpsWhoisPort, - String httpsWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java deleted file mode 100644 index 7579cc752cf..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { - private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = - new WebWhoisModule_ProvideSslProviderFactory(); - - @Override - public SslProvider get() { - return proxyProvideSslProvider(); - } - - public static WebWhoisModule_ProvideSslProviderFactory create() { - return INSTANCE; - } - - public static SslProvider proxyProvideSslProvider() { - return Preconditions.checkNotNull( - WebWhoisModule.provideSslProvider(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java deleted file mode 100644 index 37431babcb9..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpWhoisHandlerProviders( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java deleted file mode 100644 index adf393894e8..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider> sslClientInitializerProvider; - - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.sslClientInitializerProvider = sslClientInitializerProvider; - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpsWhoisHandlerProviders( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} From 66141d753f312ba9cadd29c570d8149566ca6df3 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:30:57 -0400 Subject: [PATCH 080/337] Final Changes in .gitignore --- prober/.gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index c86568e7672..89f9ac04aac 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From 3937f0818459d4e717aabc8e1aa559c6aa472279 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 16:56:54 -0400 Subject: [PATCH 081/337] Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class --- .../monitoring/blackbox/ProbingAction.java | 156 +++++++++++ .../monitoring/blackbox/Protocol.java | 16 +- .../handlers/SslClientInitializer.java | 53 +--- .../handlers/WebWhoisActionHandler.java | 184 ++++--------- .../monitoring/blackbox/TestUtils.java | 143 +++++----- .../blackbox/handlers/NettyRule.java | 96 +++---- .../blackbox/handlers/RedirectHandler.java | 5 + .../handlers/SslClientInitializerTest.java | 51 ++-- .../handlers/SslInitializerTestUtils.java | 3 +- .../handlers/WebWhoisActionHandlerTest.java | 247 ++++++++---------- 10 files changed, 485 insertions(+), 469 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java new file mode 100644 index 00000000000..6fbcadaf999 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -0,0 +1,156 @@ +// 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.monitoring.blackbox; + +import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import io.netty.util.AttributeKey; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; +import java.util.concurrent.Callable; +import javax.inject.Provider; + +/** + *Class that represents given action in sequence of probing + * + */ + + +public abstract class ProbingAction implements Callable { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Attribute Key that links channel to its {@link ProbingAction}*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** {@link ActionHandler} Associated with this {@link ProbingAction}*/ + private ActionHandler actionHandler; + + + /** + * The requisite instance of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline + */ + public ActionHandler actionHandler() { + return actionHandler; + } + + + /** {@link Timer} that rate limits probing*/ + private static final Timer timer = new HashedWheelTimer(); + + + /** actual {@link Duration} of this delay*/ + public abstract Duration delay(); + + /** message to send to server */ + public abstract O outboundMessage(); + + /** + * @return {@link Channel} object that represents connection between prober client and server + */ + public abstract Channel channel(); + + /** + * @return The {@link Protocol} instance that represents action to be tested by this part in sequences + */ + public abstract Protocol protocol(); + + /** + * + * @return {@link Builder} that lets us build a new ProbingAction by customizing abstract methods + */ + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** + * The method that calls the {@link ActionHandler} to send a message down the channel pipeline + * @return future that denotes when the action has been successfully performed + */ + + @Override + public ChannelFuture call() { + + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch(ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + } + + + + + ChannelPromise finished = channel().newPromise(); + + //Every specified time frame by delay(), we perform the next action in our sequence + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + ChannelFuture channelFuture = actionHandler().apply(outboundMessage()); + + channelFuture.addListeners( + future -> actionHandler().resetFuture(), + future -> finished.setSuccess()); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + + return finished; + } + + public abstract static class Builder, P extends ProbingAction> { + + public abstract B delay(Duration value); + + public abstract B outboundMessage(O value); + + public abstract B protocol(Protocol value); + + abstract P autoBuild(); + + public P build() { + P probingAction = autoBuild(); + probingAction.protocol().probingAction(probingAction); + return probingAction; + } + } + /** + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified + */ + static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); + } + } + +} + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 50a1d90a12c..913b7d7627e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -28,6 +28,8 @@ @AutoValue public abstract class Protocol { + public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + /** * Default names associated with each protocol */ @@ -38,6 +40,7 @@ public abstract class Protocol { private String host; private String path = ""; + private ProbingAction probingAction; /** Setter method for Protocol's host*/ public Protocol host(String host) { @@ -61,6 +64,17 @@ public String path() { return path; } + /** Setter method for Protocol's ProbingAction parent*/ + public Protocol probingAction(ProbingAction probingAction) { + this.probingAction = probingAction; + return this; + } + + /** Getter method for Protocol's path*/ + public ProbingAction probingAction() { + return probingAction; + } + /** If connection associated with Protocol is persistent, which is only EPP */ public boolean persistentConnection() { return name() == EPP_PROTOCOL_NAME; @@ -78,7 +92,7 @@ public boolean persistentConnection() { public abstract Builder toBuilder(); - public static Protocol.Builder builder() { + public static Builder builder() { return new AutoValue_Protocol.Builder(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index c62668b19b2..eeecb468fce 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -15,11 +15,12 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; + import google.registry.monitoring.blackbox.Protocol; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler.Sharable; @@ -28,9 +29,8 @@ import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslHandler; import io.netty.handler.ssl.SslProvider; -import java.security.PrivateKey; import java.security.cert.X509Certificate; -import java.util.function.Supplier; +import javax.inject.Inject; import javax.inject.Singleton; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; @@ -38,9 +38,6 @@ /** * Adds a client side SSL handler to the channel pipeline. * - *

Code is close to unchanged from {@link SslClientInitializer}

in proxy, but is modified - * for revised overall structure of connections, and to accomdate EPP connections

- * *

This must be the first handler provided for any handler provider list, if it is * provided. The type parameter {@code C} is needed so that unit tests can construct this handler * that works with {@link EmbeddedChannel}; @@ -53,59 +50,30 @@ public class SslClientInitializer extends ChannelInitializer< private final SslProvider sslProvider; private final X509Certificate[] trustedCertificates; - private final Supplier privateKeySupplier; - private final Supplier certificateSupplier; - + @Inject public SslClientInitializer(SslProvider sslProvider) { // null uses the system default trust store. - //Used for WebWhois, so we don't care about privateKey and certificates, setting them to null - this(sslProvider, null, null, null); - } - - public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, - Supplier certificateSupplier) { - //We use the default trust store here as well, setting trustCertificates to null - this(sslProvider, null, privateKeySupplier, certificateSupplier); + this(sslProvider, null); } @VisibleForTesting SslClientInitializer(SslProvider sslProvider, X509Certificate[] trustCertificates) { - this(sslProvider, trustCertificates, null, null); - } - - private SslClientInitializer( - SslProvider sslProvider, - X509Certificate[] trustCertificates, - Supplier privateKeySupplier, - Supplier certificateSupplier) { logger.atInfo().log("Client SSL Provider: %s", sslProvider); - this.sslProvider = sslProvider; this.trustedCertificates = trustCertificates; - this.privateKeySupplier = privateKeySupplier; - this.certificateSupplier = certificateSupplier; } @Override protected void initChannel(C channel) throws Exception { Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - String host = channel.attr(REMOTE_ADDRESS_KEY).get(); - - //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); - SslContextBuilder sslContextBuilder = + SslHandler sslHandler = SslContextBuilder.forClient() .sslProvider(sslProvider) - .trustManager(trustedCertificates); - if (privateKeySupplier != null && certificateSupplier != null) { - sslContextBuilder = sslContextBuilder - .keyManager(privateKeySupplier.get(), certificateSupplier.get()); - } - - SslHandler sslHandler = sslContextBuilder - .build() - .newHandler(channel.alloc(), host, protocol.port()); + .trustManager(trustedCertificates) + .build() + .newHandler(channel.alloc(), protocol.host(), protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); @@ -116,4 +84,3 @@ protected void initChannel(C channel) throws Exception { channel.pipeline().addLast(sslHandler); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index c0f7ce8ae78..1a1664a3c3c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. @@ -14,174 +14,92 @@ package google.registry.monitoring.blackbox.handlers; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import java.net.MalformedURLException; import java.net.URL; import javax.inject.Inject; -import org.joda.time.Duration; -/** - * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence - * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response - * implies a redirection it follows the redirection until either an Error Response is received, or - * {@link HttpResponseStatus.OK} is received

- */ -public class WebWhoisActionHandler extends ActionHandler { +public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** - * {@link Bootstrap} necessary for remaking connection on redirect response. - */ - private final Bootstrap bootstrap; - - /** - * {@link Protocol} for when redirected to http endpoint. - */ - private final Protocol httpWhoisProtocol; - - /** - * {@link Protocol} for when redirected to https endpoint. - */ - private final Protocol httpsWhoisProtocol; - - /** - * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. - */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } - + public WebWhoisActionHandler() {} - /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, - * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a - * response indicating a Failure, or receives a redirection response, where it follows the - * redirects until receiving one of the previous three responses. - */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { - - HttpResponseMessage response = (HttpResponseMessage) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpResponse response) throws Exception{ + if (response.status() == HttpResponseStatus.OK) { + logger.atInfo().log("Recieved Successful HttpResponseStatus"); + finished.setSuccess(); + System.out.println(response); - if (response.status().equals(HttpResponseStatus.OK)) { - logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - - //On success, we always pass message to ActionHandler's channelRead0 method. - super.channelRead0(ctx, msg); - - } else if (response.headers().get("location") != null) { + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { //Obtain url to be redirected to - URL url; - try { - url = new URL(response.headers().get("Location")); - } catch (MalformedURLException e) { - //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException( - "Redirected Location was invalid. Given Location was: " + response.headers() - .get("Location")); - } + URL url = new URL(response.headers().get("Location")); + //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); + int newPort = url.getDefaultPort(); - logger.atInfo().log(String - .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, - url.getDefaultPort(), newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); + + + Protocol oldProtocol = ctx.channel().attr(PROTOCOL_KEY).get(); + + //Build new Protocol from new attributes + ProbingAction currentAction = oldProtocol.probingAction(); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException( - "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); - } - - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); - - //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + Protocol newProtocol = Prober.portToProtocolMap.get(newPort).toBuilder().build() + .host(newHost) + .path(newPath); + + //Modify HttpRequest sent to remote host to reflect new path and host + FullHttpRequest httpRequest = ((DefaultFullHttpRequest) currentAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + + + //Create new probingAction that takes in the new Protocol and HttpRequest message + ProbingAction redirectedAction = currentAction., NewChannelAction>toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) .build(); + oldProtocol.probingAction(redirectedAction); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } - - //Once channel is closed, establish new connection to redirected host, and repeat - // same actions + logger.atInfo().log("Successfully Closed Connection"); + + //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell - // ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { - //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); + finished.setFailure(new RuntimeException()); + logger.atWarning().log(String.format("Received Response: %s", response.status())); } } - - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index c0c5831a68c..5d9a8b5a977 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,26 +14,40 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.cookie.ClientCookieEncoder; +import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.ServerCookieEncoder; -/** - * Utility class for various helper methods used in testing. - */ +/** Utility class for various helper methods used in testing. */ public class TestUtils { + public static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -54,73 +68,80 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { return response; } - /** - * Creates HttpResponse given status, redirection location, and other necessary inputs - */ - public static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - return response; + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; } - /** - * Basic outline for {@link Token} instances to be used in tests - */ - abstract static class TestToken extends Token { - - protected String host; - - protected TestToken(String host) { - this.host = host; - } - - @Override - public Token next() { - return this; + public static FullHttpRequest makeEppHttpRequest( + String content, + String host, + String path, + String accessToken, + String sslClientCertificateHash, + String clientAddress, + Cookie... cookies) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "application/epp+xml") + .set("accept", "application/epp+xml") + .set("X-SSL-Certificate", sslClientCertificateHash) + .set("X-Forwarded-For", clientAddress); + if (cookies.length != 0) { + request.headers().set("cookie", ClientCookieEncoder.STRICT.encode(cookies)); } + return request; + } - @Override - public OutboundMessageType modifyMessage(OutboundMessageType message) { - return message; - } + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); + return response; + } - @Override - public String host() { - return host; + public static FullHttpResponse makeEppHttpResponse( + String content, HttpResponseStatus status, Cookie... cookies) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "application/epp+xml"); + for (Cookie cookie : cookies) { + response.headers().add("set-cookie", ServerCookieEncoder.STRICT.encode(cookie)); } - + return response; } /** - * {@link TestToken} instance that creates new channel + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. */ - public static class NewChannelToken extends TestToken { - - public NewChannelToken(String host) { - super(host); + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); } + } - @Override - public Channel channel() { - return null; - } + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); } - /** - * {@link TestToken} instance that passes in existing channel - */ - public static class ExistingChannelToken extends TestToken { - public ExistingChannelToken(Channel channel, String host) { - super(host); - this.channel = channel; - } + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index f51f8c8fd61..399bc9c4c35 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. @@ -16,20 +16,17 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; + import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingActionTest; -import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -41,6 +38,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -51,25 +49,14 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest} - *

+ *

Used in {@link SslClientInitializerTest} */ -public final class NettyRule extends ExternalResource { - +final class NettyRule extends ExternalResource { // All I/O operations are done inside the single thread within this event loop group, which is // different from the main test thread. Therefore synchronizations are required to make sure that // certain I/O activities are finished when assertions are performed. - public NettyRule() { - eventLoopGroup = new NioEventLoopGroup(1); - } - - public NettyRule(EventLoopGroup e) { - eventLoopGroup = e; - } - - private final EventLoopGroup eventLoopGroup; + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); // Handler attached to server's channel to record the request received. private EchoHandler echoHandler; @@ -79,24 +66,32 @@ public NettyRule(EventLoopGroup e) { private Channel channel; - /** - * Sets up a server channel bound to the given local address. - */ - public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { + /** Sets up a server channel bound to the given local address. */ + void setUpServer(LocalAddress localAddress, ChannelHandler handler) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - - new WebWhoisServer(eventLoopGroup, localAddress, - ImmutableList.builder().add(handlers).add(echoHandler).build()); + ChannelInitializer serverInitializer = + new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) { + // Add the given handler + ch.pipeline().addLast(handler); + // Add the "echoHandler" last to log the incoming message and send it back + ch.pipeline().addLast(echoHandler); + } + }; + ServerBootstrap sb = + new ServerBootstrap() + .group(eventLoopGroup) + .channel(LocalServerChannel.class) + .childHandler(serverInitializer); + ChannelFuture unusedFuture = sb.bind(localAddress).syncUninterruptibly(); } - /** - * Sets up a client channel connecting to the give local address. - */ + /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, Protocol protocol, - String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -116,30 +111,20 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol) - .attr(REMOTE_ADDRESS_KEY, host); - + .attr(PROTOCOL_KEY, protocol); channel = b.connect(localAddress).syncUninterruptibly().channel(); } - private void checkReady() { + void checkReady() { checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); } - /** - * Test that custom setup to send message to current server sends right message - */ - public void assertReceivedMessage(String message) throws Exception { - assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); - - } - /** * Test that a message can go through, both inbound and outbound. * - *

The client writes the message to the server, which echos it back and saves the string in - * its promise. The client receives the echo and saves it in its promise. All these activities - * happens in the I/O thread, and this call itself returns immediately. + *

The client writes the message to the server, which echos it back and saves the string in its + * promise. The client receives the echo and saves it in its promise. All these activities happens + * in the I/O thread, and this call itself returns immediately. */ void assertThatMessagesWork() throws Exception { checkReady(); @@ -169,23 +154,21 @@ ThrowableSubject assertThatClientRootCause() { assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); } - /** * A handler that echoes back its inbound message. The message is also saved in a promise for * inspection later. */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { + private static class EchoHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture requestFuture = new CompletableFuture<>(); - public Future getRequestFuture() { + Future getRequestFuture() { return requestFuture; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // In the test we only send messages of type ByteBuf. - assertThat(msg).isInstanceOf(ByteBuf.class); String request = ((ByteBuf) msg).toString(UTF_8); // After the message is written back to the client, fulfill the promise. @@ -193,9 +176,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); } - /** - * Saves any inbound error as the cause of the promise failure. - */ + /** Saves any inbound error as the cause of the promise failure. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ChannelFuture unusedFuture = @@ -203,9 +184,7 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E } } - /** - * A handler that dumps its inbound message to a promise that can be inspected later. - */ + /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture responseFuture = new CompletableFuture<>(); @@ -226,9 +205,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception responseFuture.complete(response); } - /** - * Saves any inbound error into the failure cause of the promise. - */ + /** Saves any inbound error into the failure cause of the promise. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); @@ -245,4 +222,3 @@ private static void writeToChannelAndFlush(Channel channel, String data) { channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java new file mode 100644 index 00000000000..f7af491e39e --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox.handlers; + +public class RedirectHandler { + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 25e5608a100..6725643c48d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -15,7 +15,6 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; @@ -62,14 +61,10 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - /** - * Fake host to test if the SSL engine gets the correct peer host. - */ + /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; - /** - * Fake port to test if the SSL engine gets the correct peer port. - */ + /** Fake port to test if the SSL engine gets the correct peer port. */ private static final int SSL_PORT = 12345; @Rule @@ -82,24 +77,21 @@ public class SslClientInitializerTest { @Parameters(name = "{0}") public static SslProvider[] data() { return OpenSsl.isAvailable() - ? new SslProvider[]{SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[]{SslProvider.JDK}; + ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[] {SslProvider.JDK}; } - /** - * Saves the SNI hostname received by the server, if sent by the client. - */ + /** Saves the SNI hostname received by the server, if sent by the client. */ private String sniHostReceived; - /** - * Fake protocol saved in channel attribute. - */ - private static final Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + /** Fake protocol saved in channel attribute. */ + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .build() + .host(SSL_HOST); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -117,7 +109,6 @@ public void testSuccess_swappedInitializerWithSslHandler() throws Exception { new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); channel.attr(PROTOCOL_KEY).set(PROTOCOL); - channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -147,8 +138,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except nettyRule.setUpServer(localAddress, getServerHandler(ssc.key(), ssc.cert())); SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -174,9 +164,8 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); - - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -203,9 +192,8 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); - - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. @@ -215,4 +203,3 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E assertThat(nettyRule.getChannel().isActive()).isFalse(); } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java index 68b2919141d..7b4aae50106 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -92,4 +92,3 @@ static SSLSession setUpSslChannel( return sslHandler.engine().getSession(); } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 5a0d0908724..001c935d70a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -1,235 +1,208 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; + import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelPromise; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import javax.inject.Provider; +import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@link WebWhoisActionHandler}. - * - *

Attempts to test how well {@link WebWhoisActionHandler} works - * when responding to all possible types of responses

- */ +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; + private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; + private static final String HTTPS_REDIRECT = "https://"; + private static final String REDIRECT_HOST = "www.example.com"; + private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; - private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private final Protocol standardProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( - null, null, null, null))) - .setName("http") - .setPersistentConnection(false) - .setPort(HTTP_PORT) - .build(); + private static final Duration DEFAULT_DURATION = new Duration(0L); private EmbeddedChannel channel; private ActionHandler actionHandler; - private Provider actionHandlerProvider; - private Protocol initialProtocol; - private HttpRequestMessage msg; - - /** - * Creates default protocol with empty list of handlers and specified other inputs - */ - private Protocol createProtocol(String name, int port, boolean persistentConnection) { + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() - .setName(name) - .setPort(port) - .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) - .setPersistentConnection(persistentConnection) - .build(); + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); } - /** - * Initializes new WebWhoisActionHandler - */ - private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { - actionHandler = new WebWhoisActionHandler( - bootstrap, - standardProtocol, - standardProtocol, - messageTemplate - ); - actionHandlerProvider = () -> actionHandler; + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); } - /** - * Sets up testing channel with requisite attributes - */ + /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol) { + setupActionHandler(); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - private Bootstrap makeBootstrap(EventLoopGroup group) { - return new Bootstrap() - .group(group) - .channel(LocalChannel.class); + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group, LocalAddress address) { - WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); } - private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { - msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); - setupActionHandler(bootstrap, msg); - initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; } + @Test - public void testBasic_responseOk() { + public void testSuccess_responseOk() { //setup - setup("", null, true); + Protocol initialProtocol = createProtocol("responseOk", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); - //assesses that we successfully received good response and protocol is unchanged + //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badRequest() { + public void testSuccess_responseBad() { //setup - setup("", null, false); + Protocol initialProtocol = createProtocol("responseBad", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); - FullHttpResponse response = new HttpResponseMessage( - makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(future.isDone()).isTrue(); + assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } - @SuppressWarnings("CheckReturnValue") @Test - public void testBasic_responseFailure_badURL() { + public void testSuccess_redirectCloseChannel() { //setup - setup("", null, false); - setupChannel(initialProtocol); + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, and event is success - assertThat(future.isDone()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_redirect() { - // Sets up EventLoopGroup with 1 thread to be blocking. - EventLoopGroup group = new NioEventLoopGroup(1); - - // Sets up embedded channel. - setup("", makeBootstrap(group), false); - setupChannel(initialProtocol); + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - // Initializes LocalAddress with unique String. - String host = TARGET_HOST + System.currentTimeMillis(); - LocalAddress address = new LocalAddress(host); + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); - // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group, address); + channel.writeInbound(originalResponse); - FullHttpResponse response = - new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + host, true, false)); + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); - //checks that future has not been set to successful or a failure - assertThat(future.isDone()).isFalse(); + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } + } From f7ce9a2320cba2f8804d305ef1cc1fd7d8d4f45f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 16:58:33 -0400 Subject: [PATCH 082/337] Fixed build.gradle changes requested --- prober/build.gradle | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index fe5e08a62f5..e826fb6c37a 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -5,21 +5,13 @@ createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober dependencies { def deps = rootProject.dependencyMap - - compile deps['com.beust:jcommander'] - compile deps['com.google.api-client:google-api-client'] - compile deps['com.google.apis:google-api-services-cloudkms'] - compile deps['com.google.apis:google-api-services-monitoring'] - compile deps['com.google.apis:google-api-services-storage'] + compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] - compile deps['com.google.http-client:google-http-client'] - compile deps['com.google.monitoring-client:metrics'] - compile deps['com.google.monitoring-client:stackdriver'] compile deps['io.netty:netty-buffer'] compile deps['io.netty:netty-codec-http'] compile deps['io.netty:netty-codec'] @@ -35,10 +27,8 @@ dependencies { runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - - testCompile deps['com.google.monitoring-client:contrib'] + testCompile deps['com.google.truth:truth'] - testCompile deps['org.yaml:snakeyaml'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') From 740bd1b27df4c16bfe189969529c6ec41ca81907 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:04:45 -0400 Subject: [PATCH 083/337] Removed Files irrelevant to current pull request --- .../monitoring/blackbox/ProbingAction.java | 156 ------------ .../handlers/SslClientInitializer.java | 86 ------- .../handlers/WebWhoisActionHandler.java | 105 -------- .../blackbox/Handlers/ActionHandlerTest.java | 85 ------- .../monitoring/blackbox/TestUtils.java | 147 ------------ .../blackbox/handlers/NettyRule.java | 224 ------------------ .../blackbox/handlers/RedirectHandler.java | 5 - .../handlers/SslClientInitializerTest.java | 205 ---------------- .../handlers/SslInitializerTestUtils.java | 94 -------- .../handlers/WebWhoisActionHandlerTest.java | 208 ---------------- 10 files changed, 1315 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java deleted file mode 100644 index 6fbcadaf999..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ /dev/null @@ -1,156 +0,0 @@ -// 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.monitoring.blackbox; - -import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import io.netty.util.AttributeKey; -import java.util.concurrent.TimeUnit; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; -import javax.inject.Provider; - -/** - *Class that represents given action in sequence of probing - * - */ - - -public abstract class ProbingAction implements Callable { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** Attribute Key that links channel to its {@link ProbingAction}*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** {@link ActionHandler} Associated with this {@link ProbingAction}*/ - private ActionHandler actionHandler; - - - /** - * The requisite instance of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline - */ - public ActionHandler actionHandler() { - return actionHandler; - } - - - /** {@link Timer} that rate limits probing*/ - private static final Timer timer = new HashedWheelTimer(); - - - /** actual {@link Duration} of this delay*/ - public abstract Duration delay(); - - /** message to send to server */ - public abstract O outboundMessage(); - - /** - * @return {@link Channel} object that represents connection between prober client and server - */ - public abstract Channel channel(); - - /** - * @return The {@link Protocol} instance that represents action to be tested by this part in sequences - */ - public abstract Protocol protocol(); - - /** - * - * @return {@link Builder} that lets us build a new ProbingAction by customizing abstract methods - */ - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** - * The method that calls the {@link ActionHandler} to send a message down the channel pipeline - * @return future that denotes when the action has been successfully performed - */ - - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch(ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); - } - - - - - ChannelPromise finished = channel().newPromise(); - - //Every specified time frame by delay(), we perform the next action in our sequence - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - ChannelFuture channelFuture = actionHandler().apply(outboundMessage()); - - channelFuture.addListeners( - future -> actionHandler().resetFuture(), - future -> finished.setSuccess()); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - return finished; - } - - public abstract static class Builder, P extends ProbingAction> { - - public abstract B delay(Duration value); - - public abstract B outboundMessage(O value); - - public abstract B protocol(Protocol value); - - abstract P autoBuild(); - - public P build() { - P probingAction = autoBuild(); - probingAction.protocol().probingAction(probingAction); - return probingAction; - } - } - /** - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified - */ - static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } - -} - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java deleted file mode 100644 index eeecb468fce..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ /dev/null @@ -1,86 +0,0 @@ -// 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.monitoring.blackbox.handlers; - -import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.flogger.FluentLogger; - -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler.Sharable; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.SslProvider; -import java.security.cert.X509Certificate; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLParameters; - -/** - * Adds a client side SSL handler to the channel pipeline. - * - *

This must be the first handler provided for any handler provider list, if it is - * provided. The type parameter {@code C} is needed so that unit tests can construct this handler - * that works with {@link EmbeddedChannel}; - */ -@Singleton -@Sharable -public class SslClientInitializer extends ChannelInitializer { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - private final SslProvider sslProvider; - private final X509Certificate[] trustedCertificates; - - @Inject - public SslClientInitializer(SslProvider sslProvider) { - // null uses the system default trust store. - this(sslProvider, null); - } - - @VisibleForTesting - SslClientInitializer(SslProvider sslProvider, X509Certificate[] trustCertificates) { - logger.atInfo().log("Client SSL Provider: %s", sslProvider); - this.sslProvider = sslProvider; - this.trustedCertificates = trustCertificates; - } - - @Override - protected void initChannel(C channel) throws Exception { - Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - checkNotNull(protocol, "Protocol is not set for channel: %s", channel); - SslHandler sslHandler = - SslContextBuilder.forClient() - .sslProvider(sslProvider) - .trustManager(trustedCertificates) - .build() - .newHandler(channel.alloc(), protocol.host(), protocol.port()); - - // Enable hostname verification. - SSLEngine sslEngine = sslHandler.engine(); - SSLParameters sslParameters = sslEngine.getSSLParameters(); - sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); - sslEngine.setSSLParameters(sslParameters); - - channel.pipeline().addLast(sslHandler); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java deleted file mode 100644 index 1a1664a3c3c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2018 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.monitoring.blackbox.handlers; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import java.net.URL; -import javax.inject.Inject; - -public class WebWhoisActionHandler extends ActionHandler { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - @Inject - public WebWhoisActionHandler() {} - - @Override - public void channelRead0(ChannelHandlerContext ctx, HttpResponse response) throws Exception{ - if (response.status() == HttpResponseStatus.OK) { - logger.atInfo().log("Recieved Successful HttpResponseStatus"); - finished.setSuccess(); - System.out.println(response); - - } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { - - //Obtain url to be redirected to - URL url = new URL(response.headers().get("Location")); - - //From url, extract new host, port, and path - String newHost = url.getHost(); - String newPath = url.getPath(); - int newPort = url.getDefaultPort(); - - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); - - - Protocol oldProtocol = ctx.channel().attr(PROTOCOL_KEY).get(); - - //Build new Protocol from new attributes - ProbingAction currentAction = oldProtocol.probingAction(); - - //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort).toBuilder().build() - .host(newHost) - .path(newPath); - - //Modify HttpRequest sent to remote host to reflect new path and host - FullHttpRequest httpRequest = ((DefaultFullHttpRequest) currentAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); - - - //Create new probingAction that takes in the new Protocol and HttpRequest message - ProbingAction redirectedAction = currentAction., NewChannelAction>toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .build(); - - oldProtocol.probingAction(redirectedAction); - //close this channel as we no longer need it - ChannelFuture future = ctx.close(); - future.addListener( - f -> { - logger.atInfo().log("Successfully Closed Connection"); - - //Once channel is closed, establish new connection to redirected host, and repeat same actions - ChannelFuture secondFuture = redirectedAction.call(); - - //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - - } - ); - } else { - finished.setFailure(new RuntimeException()); - logger.atWarning().log(String.format("Received Response: %s", response.status())); - - } - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java deleted file mode 100644 index 01b93866b14..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java +++ /dev/null @@ -1,85 +0,0 @@ -// 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.monitoring.blackbox.Handlers; - -import static com.google.common.truth.Truth.assertThat; - -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelPromise; -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - - -/** Unit tests for {@link ActionHandler}. */ -@RunWith(JUnit4.class) -public class TestActionHandler { - - private final ActionHandler actionHandler = new ActionHandler(); - private EmbeddedChannel channel; - - @Before - public void setup() { - channel = new EmbeddedChannel(actionHandler); - } - - @Test - public void testHandler_Params() { - //initial check on Channel Activity - assertThat(channel.isActive()).isTrue(); - - - //Ensures channel Handler points to is right what - assertThat(actionHandler.getChannel()).isEqualTo(channel); - } - - @Test - public void testHandler_Behavior() { - //initial check on Channel Activity - assertThat(channel.isActive()).isTrue(); - - - ByteBuf outboundBuffer = Unpooled.copyInt(64); - - //Use ActionHandler's write method to check if the future returned is accurate - //and that it accurately writes out the inputBuffer - assertThat(actionHandler.apply(outboundBuffer)).isEqualTo(actionHandler.getFinished()); - assertThat(channel.outboundMessages().poll()).isEqualTo(outboundBuffer); - - //Creates Promise that is set to success when something changes on actionHandler's future - ChannelPromise testPromise = channel.newPromise(); - actionHandler.getFinished().addListener(f -> testPromise.setSuccess()); - - //Ensure that before reading inbound data, actionHandler's future stays inactive - assertThat(testPromise.isSuccess()).isFalse(); - - ByteBuf inputBuffer = Unpooled.copyInt(128); - - //Check that ActionHandler doesn't do anything to inbound Buffer - assertThat(channel.writeInbound(inputBuffer)).isFalse(); - - - //ensures that actionHandler's future's listener is active and that it is set to success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(actionHandler.getFinished().isSuccess()).isTrue(); - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java deleted file mode 100644 index 5d9a8b5a977..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ /dev/null @@ -1,147 +0,0 @@ -// 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.US_ASCII; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; -import io.netty.handler.codec.http.cookie.ClientCookieEncoder; -import io.netty.handler.codec.http.cookie.Cookie; -import io.netty.handler.codec.http.cookie.ServerCookieEncoder; - -/** Utility class for various helper methods used in testing. */ -public class TestUtils { - - public static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - - public static FullHttpRequest makeHttpGetRequest(String host, String path) { - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); - request.headers().set("host", host).setInt("content-length", 0); - return request; - } - - public static FullHttpResponse makeHttpResponse(String content, HttpResponseStatus status) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buf); - response.headers().setInt("content-length", buf.readableBytes()); - return response; - } - - public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status); - response.headers().setInt("content-length", 0); - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpRequest makeEppHttpRequest( - String content, - String host, - String path, - String accessToken, - String sslClientCertificateHash, - String clientAddress, - Cookie... cookies) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "application/epp+xml") - .set("accept", "application/epp+xml") - .set("X-SSL-Certificate", sslClientCertificateHash) - .set("X-Forwarded-For", clientAddress); - if (cookies.length != 0) { - request.headers().set("cookie", ClientCookieEncoder.STRICT.encode(cookies)); - } - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); - return response; - } - - public static FullHttpResponse makeEppHttpResponse( - String content, HttpResponseStatus status, Cookie... cookies) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "application/epp+xml"); - for (Cookie cookie : cookies) { - response.headers().add("set-cookie", ServerCookieEncoder.STRICT.encode(cookie)); - } - return response; - } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java deleted file mode 100644 index 399bc9c4c35..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright 2018 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.monitoring.blackbox.handlers; - -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.base.Throwables; -import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.ReferenceCountUtil; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import org.junit.rules.ExternalResource; - -/** - * Helper for setting up and testing client / server connection with netty. - * - *

Used in {@link SslClientInitializerTest} - */ -final class NettyRule extends ExternalResource { - - // All I/O operations are done inside the single thread within this event loop group, which is - // different from the main test thread. Therefore synchronizations are required to make sure that - // certain I/O activities are finished when assertions are performed. - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - - // Handler attached to server's channel to record the request received. - private EchoHandler echoHandler; - - // Handler attached to client's channel to record the response received. - private DumpHandler dumpHandler; - - private Channel channel; - - /** Sets up a server channel bound to the given local address. */ - void setUpServer(LocalAddress localAddress, ChannelHandler handler) { - checkState(echoHandler == null, "Can't call setUpServer twice"); - echoHandler = new EchoHandler(); - ChannelInitializer serverInitializer = - new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) { - // Add the given handler - ch.pipeline().addLast(handler); - // Add the "echoHandler" last to log the incoming message and send it back - ch.pipeline().addLast(echoHandler); - } - }; - ServerBootstrap sb = - new ServerBootstrap() - .group(eventLoopGroup) - .channel(LocalServerChannel.class) - .childHandler(serverInitializer); - ChannelFuture unusedFuture = sb.bind(localAddress).syncUninterruptibly(); - } - - /** Sets up a client channel connecting to the give local address. */ - void setUpClient( - LocalAddress localAddress, - Protocol protocol, - ChannelHandler handler) { - checkState(echoHandler != null, "Must call setUpServer before setUpClient"); - checkState(dumpHandler == null, "Can't call setUpClient twice"); - dumpHandler = new DumpHandler(); - ChannelInitializer clientInitializer = - new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) throws Exception { - // Add the given handler - ch.pipeline().addLast(handler); - // Add the "dumpHandler" last to log the incoming message - ch.pipeline().addLast(dumpHandler); - } - }; - Bootstrap b = - new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class) - .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol); - channel = b.connect(localAddress).syncUninterruptibly().channel(); - } - - void checkReady() { - checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); - } - - /** - * Test that a message can go through, both inbound and outbound. - * - *

The client writes the message to the server, which echos it back and saves the string in its - * promise. The client receives the echo and saves it in its promise. All these activities happens - * in the I/O thread, and this call itself returns immediately. - */ - void assertThatMessagesWork() throws Exception { - checkReady(); - assertThat(channel.isActive()).isTrue(); - - writeToChannelAndFlush(channel, "Hello, world!"); - assertThat(echoHandler.getRequestFuture().get()).isEqualTo("Hello, world!"); - assertThat(dumpHandler.getResponseFuture().get()).isEqualTo("Hello, world!"); - } - - Channel getChannel() { - checkReady(); - return channel; - } - - ThrowableSubject assertThatServerRootCause() { - checkReady(); - return assertThat( - Throwables.getRootCause( - assertThrows(ExecutionException.class, () -> echoHandler.getRequestFuture().get()))); - } - - ThrowableSubject assertThatClientRootCause() { - checkReady(); - return assertThat( - Throwables.getRootCause( - assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); - } - - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - private static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } - - /** A handler that dumps its inbound message to a promise that can be inspected later. */ - private static class DumpHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture responseFuture = new CompletableFuture<>(); - - Future getResponseFuture() { - return responseFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - // There is no more use of this message, we should release its reference count so that it - // can be more effectively garbage collected by Netty. - ReferenceCountUtil.release(msg); - // Save the string in the promise and make it as complete. - responseFuture.complete(response); - } - - /** Saves any inbound error into the failure cause of the promise. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); - } - } - - @Override - protected void after() { - Future unusedFuture = eventLoopGroup.shutdownGracefully(); - } - - private static void writeToChannelAndFlush(Channel channel, String data) { - ChannelFuture unusedFuture = - channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java deleted file mode 100644 index f7af491e39e..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -public class RedirectHandler { - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java deleted file mode 100644 index 6725643c48d..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ /dev/null @@ -1,205 +0,0 @@ -// 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.monitoring.blackbox.handlers; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; -import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; -import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SniHandler; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.SslProvider; -import io.netty.handler.ssl.util.SelfSignedCertificate; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.cert.CertPathBuilderException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import javax.net.ssl.SSLException; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; - -/** - * Unit tests for {@link SslClientInitializer}. - * - *

To validate that the handler accepts & rejects connections as expected, a test server and a - * test client are spun up, and both connect to the {@link LocalAddress} within the JVM. This avoids - * the overhead of routing traffic through the network layer, even if it were to go through - * loopback. It also alleviates the need to pick a free port to use. - * - *

The local addresses used in each test method must to be different, otherwise tests run in - * parallel may interfere with each other. - */ -@RunWith(Parameterized.class) -public class SslClientInitializerTest { - - /** Fake host to test if the SSL engine gets the correct peer host. */ - private static final String SSL_HOST = "www.example.tld"; - - /** Fake port to test if the SSL engine gets the correct peer port. */ - private static final int SSL_PORT = 12345; - - @Rule - public NettyRule nettyRule = new NettyRule(); - - @Parameter(0) - public SslProvider sslProvider; - - // We do our best effort to test all available SSL providers. - @Parameters(name = "{0}") - public static SslProvider[] data() { - return OpenSsl.isAvailable() - ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[] {SslProvider.JDK}; - } - - /** Saves the SNI hostname received by the server, if sent by the client. */ - private String sniHostReceived; - - /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .build() - .host(SSL_HOST); - - private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) - throws Exception { - SslContext sslContext = SslContextBuilder.forServer(privateKey, certificate).build(); - return new SniHandler( - hostname -> { - sniHostReceived = hostname; - return sslContext; - }); - } - - @Test - public void testSuccess_swappedInitializerWithSslHandler() throws Exception { - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider); - EmbeddedChannel channel = new EmbeddedChannel(); - channel.attr(PROTOCOL_KEY).set(PROTOCOL); - ChannelPipeline pipeline = channel.pipeline(); - pipeline.addLast(sslClientInitializer); - ChannelHandler firstHandler = pipeline.first(); - assertThat(firstHandler.getClass()).isEqualTo(SslHandler.class); - SslHandler sslHandler = (SslHandler) firstHandler; - assertThat(sslHandler.engine().getPeerHost()).isEqualTo(SSL_HOST); - assertThat(sslHandler.engine().getPeerPort()).isEqualTo(SSL_PORT); - assertThat(channel.isActive()).isTrue(); - } - - @Test - public void testSuccess_protocolAttributeNotSet() { - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider); - EmbeddedChannel channel = new EmbeddedChannel(); - ChannelPipeline pipeline = channel.pipeline(); - pipeline.addLast(sslClientInitializer); - // Channel initializer swallows error thrown, and closes the connection. - assertThat(channel.isActive()).isFalse(); - } - - @Test - public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Exception { - SelfSignedCertificate ssc = new SelfSignedCertificate(SSL_HOST); - LocalAddress localAddress = - new LocalAddress("DEFAULT_TRUST_MANAGER_REJECT_SELF_SIGNED_CERT_" + sslProvider); - nettyRule.setUpServer(localAddress, getServerHandler(ssc.key(), ssc.cert())); - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider); - nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); - // The connection is now terminated, both the client side and the server side should get - // exceptions. - nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); - nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); - assertThat(nettyRule.getChannel().isActive()).isFalse(); - } - - @Test - public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws Exception { - LocalAddress localAddress = - new LocalAddress("CUSTOM_TRUST_MANAGER_ACCEPT_CERT_SIGNED_BY_TRUSTED_CA_" + sslProvider); - - // Generate a new key pair. - KeyPair keyPair = getKeyPair(); - - // Generate a self signed certificate, and use it to sign the key pair. - SelfSignedCertificate ssc = new SelfSignedCertificate(); - X509Certificate cert = signKeyPair(ssc, keyPair, SSL_HOST); - - // Set up the server to use the signed cert and private key to perform handshake; - PrivateKey privateKey = keyPair.getPrivate(); - nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); - - // Set up the client to trust the self signed cert used to sign the cert that server provides. - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); - - setUpSslChannel(nettyRule.getChannel(), cert); - nettyRule.assertThatMessagesWork(); - - // Verify that the SNI extension is sent during handshake. - assertThat(sniHostReceived).isEqualTo(SSL_HOST); - } - - @Test - public void testFailure_customTrustManager_wrongHostnameInCertificate() throws Exception { - LocalAddress localAddress = - new LocalAddress("CUSTOM_TRUST_MANAGER_WRONG_HOSTNAME_" + sslProvider); - - // Generate a new key pair. - KeyPair keyPair = getKeyPair(); - - // Generate a self signed certificate, and use it to sign the key pair. - SelfSignedCertificate ssc = new SelfSignedCertificate(); - X509Certificate cert = signKeyPair(ssc, keyPair, "wrong.com"); - - // Set up the server to use the signed cert and private key to perform handshake; - PrivateKey privateKey = keyPair.getPrivate(); - nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); - - // Set up the client to trust the self signed cert used to sign the cert that server provides. - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); - - // When the client rejects the server cert due to wrong hostname, both the client and server - // should throw exceptions. - nettyRule.assertThatClientRootCause().isInstanceOf(CertificateException.class); - nettyRule.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST); - nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); - assertThat(nettyRule.getChannel().isActive()).isFalse(); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java deleted file mode 100644 index 7b4aae50106..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java +++ /dev/null @@ -1,94 +0,0 @@ -// 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.monitoring.blackbox.handlers; - -import static com.google.common.truth.Truth.assertThat; - -import io.netty.channel.Channel; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.util.SelfSignedCertificate; -import java.math.BigInteger; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.SecureRandom; -import java.security.Security; -import java.security.cert.X509Certificate; -import java.time.Duration; -import java.time.Instant; -import java.util.Date; -import javax.net.ssl.SSLSession; -import javax.security.auth.x500.X500Principal; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.x509.X509V3CertificateGenerator; - -/** - * Utility class that provides methods used by {@link SslClientInitializerTest} - */ -public class SslInitializerTestUtils { - - static { - Security.addProvider(new BouncyCastleProvider()); - } - - public static KeyPair getKeyPair() throws Exception { - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); - keyPairGenerator.initialize(2048, new SecureRandom()); - return keyPairGenerator.generateKeyPair(); - } - - /** - * Signs the given key pair with the given self signed certificate. - * - * @return signed public key (of the key pair) certificate - */ - public static X509Certificate signKeyPair( - SelfSignedCertificate ssc, KeyPair keyPair, String hostname) throws Exception { - X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); - X500Principal dnName = new X500Principal("CN=" + hostname); - certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); - certGen.setSubjectDN(dnName); - certGen.setIssuerDN(ssc.cert().getSubjectX500Principal()); - certGen.setNotBefore(Date.from(Instant.now().minus(Duration.ofDays(1)))); - certGen.setNotAfter(Date.from(Instant.now().plus(Duration.ofDays(1)))); - certGen.setPublicKey(keyPair.getPublic()); - certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); - return certGen.generate(ssc.key(), "BC"); - } - - /** - * Verifies tha the SSL channel is established as expected, and also sends a message to the server - * and verifies if it is echoed back correctly. - * - * @param certs The certificate that the server should provide. - * @return The SSL session in current channel, can be used for further validation. - */ - static SSLSession setUpSslChannel( - Channel channel, - X509Certificate... certs) - throws Exception { - SslHandler sslHandler = channel.pipeline().get(SslHandler.class); - // Wait till the handshake is complete. - sslHandler.handshakeFuture().get(); - - assertThat(channel.isActive()).isTrue(); - assertThat(sslHandler.handshakeFuture().isSuccess()).isTrue(); - assertThat(sslHandler.engine().getSession().isValid()).isTrue(); - assertThat(sslHandler.engine().getSession().getPeerCertificates()) - .asList() - .containsExactlyElementsIn(certs); - // Returns the SSL session for further assertion. - return sslHandler.engine().getSession(); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java deleted file mode 100644 index 001c935d70a..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ /dev/null @@ -1,208 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; - - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelPromise; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import org.joda.time.Duration; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ -@RunWith(JUnit4.class) -public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; - private static final int HTTPS_PORT = 443; - private static final String HTTP_REDIRECT = "http://"; - private static final String HTTPS_REDIRECT = "https://"; - private static final String REDIRECT_HOST = "www.example.com"; - private static final String REDIRECT_PATH = "/test/path"; - private static final String TARGET_HOST = "whois.nic.tld"; - private static final Duration DEFAULT_DURATION = new Duration(0L); - - - private EmbeddedChannel channel; - private ActionHandler actionHandler; - - /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { - return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); - } - - /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); - } - - /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); - } - - /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .build(); - } - - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); - } - - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - - @Test - public void testSuccess_responseOk() { - //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); - - //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); - - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that we successfully receivved good response and protocol is unchanged - assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); - } - - @Test - public void testSuccess_responseBad() { - //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); - - //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - - //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); - } - - @Test - public void testSuccess_redirectCloseChannel() { - //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); - - //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); - - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - - - channel.writeInbound(response); - - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - - - } - - @Test - public void testSuccess_redirectHost() { - //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - - //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - - - channel.writeInbound(originalResponse); - - //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - - - } - -} From 3cf99cb7ea8f80d9c2e9f2830f4ce80165f0fa42 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 10 Jul 2019 17:34:38 -0400 Subject: [PATCH 084/337] Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle --- .../monitoring/blackbox/package-info.java | 15 --------------- .../monitoring/blackbox/package-info.java | 15 --------------- settings.gradle | 5 ++--- 3 files changed, 2 insertions(+), 33 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/package-info.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/package-info.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java deleted file mode 100644 index 21c8764701c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java +++ /dev/null @@ -1,15 +0,0 @@ -// 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.monitoring.blackbox; \ No newline at end of file diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java deleted file mode 100644 index 21c8764701c..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java +++ /dev/null @@ -1,15 +0,0 @@ -// 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.monitoring.blackbox; \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 0cd8f4dd707..eea358cfc0e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -30,11 +30,10 @@ rootProject.name = 'nomulus' include 'core' include 'prober' include 'proxy' -include 'third_party' -include 'util' include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' -include 'prober' +include 'third_party' +include 'util' From 3b793c09125436b11fbba54ceb0f01db9b8a1d06 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 10 Jul 2019 17:41:55 -0400 Subject: [PATCH 085/337] Fully Updated ActionHandler (missing updated JavaDoc) --- .../blackbox/handlers/ActionHandler.java | 58 +++++++------------ 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index a4df56408b5..c502f94015f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -15,72 +15,58 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import com.google.common.flogger.StackSize; -import io.netty.channel.ChannelInboundHandlerAdapter; +import google.registry.monitoring.blackbox.messages.InboundMarker; +import google.registry.monitoring.blackbox.messages.OutboundMarker; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpResponse; -import java.util.function.Function; -import javax.inject.Inject; /** * - * @param Generic Type of Inbound Message - * @param Generic Type of Outbound Message + * * Abstract class that tells sends message down pipeline and * and tells listeners to move on when the message is received. */ -public abstract class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); protected ChannelPromise finished; - private Channel channel; - + protected OutboundMarker outboundMessage; - /** returns ChannelPromise for when inbound message is recieved - * a - * @param outboundMessage - * @return - */ - @Override - public ChannelFuture apply(O outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline + /** Writes and flushes specified outboundMessage to channel pipeline and returns future + * that is marked as success when ActionHandler next reads from the channel */ + public ChannelFuture getFuture(OutboundMarker outboundMessage) { + //Action Handlers subclasses require the outboundMessage for additional logic + this.outboundMessage = outboundMessage; - channel.writeAndFlush(outboundMessage); + //returns the ChannelPromise initialized return finished; - - } - - public void resetFuture() { - finished = channel.newPromise(); } @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler - - channel = ctx.channel(); finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ - //Only purpose of Handler is to mark future as a success - + public void channelRead0(ChannelHandlerContext ctx, InboundMarker inboundMessage) throws Exception { + //simply marks finished as success finished.setSuccess(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); + logger.atSevere().withCause(cause).log(String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), + ctx.channel().pipeline().toString())); + + finished.setFailure(cause); + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } From f25c42eae2b887c9cfff1a669f1e84197f20f58f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 10 Jul 2019 17:54:18 -0400 Subject: [PATCH 086/337] Added changed Protocol and both Inbound and Outbound Markers --- .../monitoring/blackbox/Protocol.java | 65 +++++-------------- .../blackbox/messages/InboundMarker.java | 22 +++++++ .../blackbox/messages/OutboundMarker.java | 21 ++++++ 3 files changed, 58 insertions(+), 50 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 913b7d7627e..8e39866cd56 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -16,6 +16,7 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; import javax.inject.Provider; @@ -29,7 +30,7 @@ public abstract class Protocol { public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); /** * Default names associated with each protocol */ @@ -38,77 +39,41 @@ public abstract class Protocol { final static String WHOIS_PROTOCOL_NAME = "WHOIS"; final static String RDAP_PROTOCOL_NAME = "RDAP"; - private String host; - private String path = ""; - private ProbingAction probingAction; - - /** Setter method for Protocol's host*/ - public Protocol host(String host) { - this.host = host; - return this; - } - - /** Getter method for Protocol's host*/ - public String host() { - return host; - } - - /** Setter method for Protocol's path*/ - public Protocol path(String path) { - this.path = path; - return this; - } - - /** Getter method for Protocol's path*/ - public String path() { - return path; - } - - /** Setter method for Protocol's ProbingAction parent*/ - public Protocol probingAction(ProbingAction probingAction) { - this.probingAction = probingAction; - return this; - } - - /** Getter method for Protocol's path*/ - public ProbingAction probingAction() { - return probingAction; - } - - /** If connection associated with Protocol is persistent, which is only EPP */ - public boolean persistentConnection() { - return name() == EPP_PROTOCOL_NAME; - } + /** Local Address of Protocol. ONLY FOR TESTING*/ + public abstract LocalAddress address(); /** Protocol Name */ - public abstract String name(); + abstract String name(); /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - public abstract ImmutableList> handlerProviders(); + abstract ImmutableList> handlerProviders(); + /** If connection associated with Protocol is persistent, which is only EPP */ + abstract boolean persistentConnection(); public abstract Builder toBuilder(); public static Builder builder() { - return new AutoValue_Protocol.Builder(); + return new AutoValue_Protocol.Builder().address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder { + public abstract Builder address(LocalAddress value); + public abstract Builder name(String value); public abstract Builder port(int num); public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder persistentConnection(boolean value); + public abstract Protocol build(); } - - - } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java new file mode 100644 index 00000000000..0a16344eb65 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java @@ -0,0 +1,22 @@ +// Copyright 2019 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.monitoring.blackbox.messages; + +/** + * Simple Interface that is implemented by all classes that serve + * as inboundMessages in the channel pipelines + */ +public interface InboundMarker {} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java new file mode 100644 index 00000000000..413a97ea0a0 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java @@ -0,0 +1,21 @@ +// Copyright 2019 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.monitoring.blackbox.messages; + +/** + * Simple Interface that is implemented by all classes that serve + * as outboundMessages in the channel pipelines + */ +public interface OutboundMarker {} From 1a72d764573482b63d9860267231290edd7c8120 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 09:25:54 -0400 Subject: [PATCH 087/337] Removed AutoVaue ignore clause from .gitignore --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 199c4fe3979..327b22fe2e7 100644 --- a/.gitignore +++ b/.gitignore @@ -85,9 +85,6 @@ nomulus.iws # Javascript output **/out/* -# AutoValue generated code -AutoValue_.*.java - ###################################################################### # Python Ignores From d25c7d4fabe70c3c4fc4f04a215e7b2f628b5234 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:23:33 -0400 Subject: [PATCH 088/337] removed unneccessary dependencies in build.gradle --- prober/build.gradle | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index e826fb6c37a..0f7931519b3 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,15 +1,25 @@ +// Copyright 2019 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. + apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] - compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] compile deps['io.netty:netty-buffer'] @@ -18,26 +28,16 @@ dependencies { compile deps['io.netty:netty-common'] compile deps['io.netty:netty-handler'] compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - //compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor annotationProcessor deps['com.google.auto.value:auto-value'] testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] -} \ No newline at end of file +} + From f5e18141d448319d7b2a8bf24d22442259e06803 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:47:39 -0400 Subject: [PATCH 089/337] Fixed Javadoc and comments for ActionHandler --- .../blackbox/handlers/ActionHandler.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index c502f94015f..814efd01e33 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -23,10 +23,16 @@ import io.netty.channel.ChannelPromise; /** + *Superclass of all Handlers placed at end of channel pipeline * + *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler}, as it should only be passed in + * messages that implement the {@link InboundMarker} interface.

* - * Abstract class that tells sends message down pipeline and - * and tells listeners to move on when the message is received. + *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMarker} + * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception + * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses + * specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -35,16 +41,16 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); } } - From efaa9b0493ec37133ec237149cc3044dcbf472b7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:55:18 -0400 Subject: [PATCH 090/337] Fixed comments and JavaDoc on other files --- prober/build.gradle | 7 +++++++ .../monitoring/blackbox/Protocol.java | 19 +++---------------- .../blackbox/messages/InboundMarker.java | 3 +-- .../blackbox/messages/OutboundMarker.java | 3 +-- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 0f7931519b3..4590fe28148 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -20,6 +20,7 @@ dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] compile deps['io.netty:netty-buffer'] @@ -28,16 +29,22 @@ dependencies { compile deps['io.netty:netty-common'] compile deps['io.netty:netty-handler'] compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') // Include auto-value in compile until nebula-lint understands // annotationProcessor annotationProcessor deps['com.google.auto.value:auto-value'] testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 8e39866cd56..080acc30584 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -17,41 +17,29 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import io.netty.channel.local.LocalAddress; -import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; import javax.inject.Provider; /** - * Protocol Class packages all static variables necessary for a certain type of connection - * Both the host and the path can be changed for the same protocol - * Mainly packages the handlers necessary for the requisite channel pipeline + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection */ @AutoValue public abstract class Protocol { - public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** - * Default names associated with each protocol - */ - final static String EPP_PROTOCOL_NAME = "EPP"; - final static String DNS_PROTOCOL_NAME = "DNS"; - final static String WHOIS_PROTOCOL_NAME = "WHOIS"; - final static String RDAP_PROTOCOL_NAME = "RDAP"; /** Local Address of Protocol. ONLY FOR TESTING*/ public abstract LocalAddress address(); - /** Protocol Name */ abstract String name(); - /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ abstract ImmutableList> handlerProviders(); - /** If connection associated with Protocol is persistent, which is only EPP */ + /** Boolean that notes if connection associated with Protocol is persistent.*/ abstract boolean persistentConnection(); public abstract Builder toBuilder(); @@ -76,4 +64,3 @@ public static abstract class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java index 0a16344eb65..edd541f98f7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java @@ -15,8 +15,7 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve - * as inboundMessages in the channel pipelines + * Simple Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ public interface InboundMarker {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java index 413a97ea0a0..eb2c14e8096 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java @@ -15,7 +15,6 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve - * as outboundMessages in the channel pipelines + * Simple Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMarker {} From 4dc641155dfd0ec8c8207ee759b61a92fda12653 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:57:07 -0400 Subject: [PATCH 091/337] EOL added --- .../main/java/google/registry/monitoring/blackbox/Protocol.java | 1 + .../registry/monitoring/blackbox/handlers/ActionHandler.java | 1 + .../registry/monitoring/blackbox/messages/OutboundMarker.java | 1 + 3 files changed, 3 insertions(+) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 080acc30584..fa9f3814ddc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -64,3 +64,4 @@ public static abstract class Builder { public abstract Protocol build(); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 814efd01e33..c26882e5f4c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -76,3 +76,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java index eb2c14e8096..bd80aa0a062 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java @@ -18,3 +18,4 @@ * Simple Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMarker {} + From 6c6d091e5d649473cd36cb8589d2094efeef4622 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 12 Jul 2019 12:10:20 -0400 Subject: [PATCH 092/337] Removed Unnecessary Files --- .../google/registry/monitoring/blackbox/ActionHandler.java | 5 ----- .../google/registry/monitoring/blackbox/ProbingAction.java | 5 ----- .../google/registry/monitoring/blackbox/ProbingSequence.java | 5 ----- .../google/registry/monitoring/blackbox/ProbingStep.java | 5 ----- .../java/google/registry/monitoring/blackbox/Protocol.java | 5 ----- .../java/google/registry/monitoring/blackbox/TestToken.java | 5 ----- .../main/java/google/registry/monitoring/blackbox/Token.java | 5 ----- 7 files changed, 35 deletions(-) delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java deleted file mode 100644 index a4d36657721..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ActionHandler { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java deleted file mode 100644 index 6b26913d425..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingAction { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java deleted file mode 100644 index 9f3617135a4..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingSequence { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java deleted file mode 100644 index b8b237a1e91..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingStep { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java deleted file mode 100644 index 75d13b3039a..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Protocol { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java deleted file mode 100644 index 98f21f8d63a..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class TestToken { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java deleted file mode 100644 index 16f05be0430..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Token { - -} From 9ff8bc594ef2816b1646c3c989e1a3f8e4155cdf Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 12 Jul 2019 13:32:44 -0400 Subject: [PATCH 093/337] fixed .gradle files styles --- settings.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.gradle b/settings.gradle index eea358cfc0e..10ae29b66d1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -30,10 +30,10 @@ rootProject.name = 'nomulus' include 'core' include 'prober' include 'proxy' +include 'third_party' +include 'util' include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' -include 'third_party' -include 'util' From 84bbd05e0736af73104ec28f5e31d50eb02e70e9 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 15:15:52 -0400 Subject: [PATCH 094/337] Removed outbound message from ActionHandler's fields and renamed Marker Interfaces --- .../blackbox/handlers/ActionHandler.java | 9 ++------ .../blackbox/messages/InboundMarker.java | 21 ------------------- .../blackbox/messages/InboundMessageType.java | 5 ++--- .../blackbox/messages/OutboundMarker.java | 21 ------------------- .../messages/OutboundMessageType.java | 19 ++--------------- 5 files changed, 6 insertions(+), 69 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index c26882e5f4c..22df091833d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -23,7 +23,7 @@ import io.netty.channel.ChannelPromise; /** - *Superclass of all Handlers placed at end of channel pipeline + *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler}, as it should only be passed in * messages that implement the {@link InboundMarker} interface.

@@ -39,14 +39,9 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler Date: Mon, 15 Jul 2019 15:17:40 -0400 Subject: [PATCH 095/337] Fixed javadoc for Marker Interfaced --- .../monitoring/blackbox/messages/InboundMessageType.java | 2 +- .../monitoring/blackbox/messages/OutboundMessageType.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 7f4b4135516..0c1260becf2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ public interface InboundMessageType {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index e1ed12f56d9..0dd17e9d4a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType {} From 8b6f292a47810299f3cd2a0b745f7f204060550e Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 15:18:51 -0400 Subject: [PATCH 096/337] Modified Comments on ActionHandler --- .../blackbox/handlers/ActionHandler.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 22df091833d..dfd88cba1ce 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,8 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.messages.InboundMarker; -import google.registry.monitoring.blackbox.messages.OutboundMarker; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -25,22 +25,22 @@ /** *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler}, as it should only be passed in - * messages that implement the {@link InboundMarker} interface.

+ *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMarker} + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses * specify further work to be done for specific kinds of channel pipelines.

*/ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); protected ChannelPromise finished; - /** Takes in {@link OutboundMarker} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ public ChannelFuture getFuture() { return finished; } @@ -53,7 +53,7 @@ public void handlerAdded(ChannelHandlerContext ctx) { } @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMarker inboundMessage) throws Exception { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws Exception { //simply marks finished as success finished.setSuccess(); } From 4e6c00ebcfac316b1dddb65d4bcfd5d47809ef53 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 15:40:37 -0400 Subject: [PATCH 097/337] Removed LocalAddress from Protocol --- .../google/registry/monitoring/blackbox/Protocol.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index fa9f3814ddc..b0071ea4467 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,7 +16,6 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.local.LocalAddress; import io.netty.channel.ChannelHandler; import javax.inject.Provider; @@ -26,12 +25,6 @@ @AutoValue public abstract class Protocol { - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - - /** Local Address of Protocol. ONLY FOR TESTING*/ - public abstract LocalAddress address(); - abstract String name(); public abstract int port(); @@ -45,14 +38,12 @@ public abstract class Protocol { public abstract Builder toBuilder(); public static Builder builder() { - return new AutoValue_Protocol.Builder().address(DEFAULT_ADDRESS); + return new AutoValue_Protocol.Builder(); } @AutoValue.Builder public static abstract class Builder { - public abstract Builder address(LocalAddress value); - public abstract Builder name(String value); public abstract Builder port(int num); From 2c3f14c8bc90ca8c9d22e400078e09afcad5302b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 16:13:43 -0400 Subject: [PATCH 098/337] Fixed Travis Build Issues --- prober/build.gradle | 5 ++--- settings.gradle | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 4590fe28148..e287bfd1bb9 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -18,7 +18,7 @@ createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober dependencies { def deps = rootProject.dependencyMap - + compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] @@ -34,7 +34,7 @@ dependencies { runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - + testCompile deps['com.google.truth:truth'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] @@ -47,4 +47,3 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } - diff --git a/settings.gradle b/settings.gradle index 10ae29b66d1..9b2d11de8da 100644 --- a/settings.gradle +++ b/settings.gradle @@ -36,4 +36,3 @@ include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' - From 91b5b583f6e4bc506915f5cac50a28e8d4c8bce8 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 099/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 3 +- .../google/registry/xjc/package-info.java | 3 +- prober/build.gradle | 33 ++-- .../monitoring/blackbox/NewChannelAction.java | 136 +++++++++++++ .../registry/monitoring/blackbox/Prober.java | 23 +-- .../monitoring/blackbox/ProbingAction.java | 186 ++++++++++++++++++ .../handlers/ServerSideException.java | 15 ++ .../handlers/SslClientInitializer.java | 117 +++++++++++ .../handlers/WebWhoisActionHandler.java | 137 +++++++++++++ .../blackbox/messages/HttpRequestMessage.java | 71 ++----- .../messages/HttpResponseMessage.java | 46 +++-- .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 15 files changed, 653 insertions(+), 125 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index ddff37c6807..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,3 +14,4 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.ui; + diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 5b5456585cc..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,3 +14,4 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.xjc; + diff --git a/prober/build.gradle b/prober/build.gradle index e287bfd1bb9..a277fb4f9f3 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -4,7 +4,7 @@ // 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 +// 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, @@ -12,12 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -apply plugin: 'java' - createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') dependencies { - def deps = rootProject.dependencyMap + def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.dagger:dagger'] @@ -30,20 +28,21 @@ dependencies { compile deps['io.netty:netty-handler'] compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] - runtime deps['com.google.flogger:flogger-system-backend'] - runtime deps['com.google.auto.value:auto-value'] - runtime deps['io.netty:netty-tcnative-boringssl-static'] + runtime deps['com.google.flogger:flogger-system-backend'] + runtime deps['com.google.auto.value:auto-value'] + runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') - // Include auto-value in compile until nebula-lint understands - // annotationProcessor - annotationProcessor deps['com.google.auto.value:auto-value'] - testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] + // Include auto-value in compile until nebula-lint understands + // annotationProcessor + annotationProcessor deps['com.google.auto.value:auto-value'] + testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..0ba3a0c22be --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 433d7361d5b..333330207f1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,30 +14,17 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by - * Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** - * Main Dagger Component - */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() - .build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java new file mode 100644 index 00000000000..2441debb12d --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -0,0 +1,186 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.flogger.StackSize.SMALL; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.util.AttributeKey; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; +import java.util.concurrent.Callable; +import javax.inject.Provider; + +/** + *Superclass that represents action generated by {@link ProbingStep} + * + *

Inherits from {@link Callable}, as it has can be called + * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the + * task has been completed

+ * + *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. + * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} + * gives the outline and {@link ProbingAction} gives the details of that connection.

+ * + *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ */ + + +public abstract class ProbingAction implements Callable { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; + + + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; + } + + /** {@link Timer} that rate limits probing */ + private static final Timer timer = new HashedWheelTimer(); + + + /** Actual {@link Duration} of this delay */ + public abstract Duration delay(); + + /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ + public abstract OutboundMessageType outboundMessage(); + + /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + public abstract Channel channel(); + + /** The {@link Protocol} instance that specifies type of connection */ + public abstract Protocol protocol(); + + public abstract String host(); + + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> finished.setSuccess(), + future -> { + if (!protocol().persistentConnection()) { + + //If we created a new channel for this action, close the connection to the channel + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** + * The method that sends the {@code outboundMessage} down the channel pipeline + * + * @return future that denotes when the action has been successfully performed + */ + + @Override + public ChannelFuture call() { + + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + } + + //ChannelPromise that we use to inform ProbingStep when we are finished. + ChannelPromise finished = channel().newPromise(); + + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } + + return finished; + } + + public abstract static class Builder, P extends ProbingAction> { + + public abstract B delay(Duration value); + + public abstract B outboundMessage(OutboundMessageType value); + + public abstract B protocol(Protocol value); + + public abstract B host(String value); + + public abstract B path(String value); + + public abstract P build(); + + } + + /** + * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified + * + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified + */ + static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); + } + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java new file mode 100644 index 00000000000..ac844ac99df --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -0,0 +1,117 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.base.Preconditions.checkNotNull; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.flogger.FluentLogger; + +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslProvider; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.function.Supplier; +import javax.inject.Singleton; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; + +/** + * Adds a client side SSL handler to the channel pipeline. + * + *

Code is close to unchanged from {@link SslClientInitializer}

in proxy, but is modified + * for revised overall structure of connections, and to accomdate EPP connections

+ * + *

This must be the first handler provided for any handler provider list, if it is + * provided. The type parameter {@code C} is needed so that unit tests can construct this handler + * that works with {@link EmbeddedChannel}; + */ +@Singleton +@Sharable +public class SslClientInitializer extends ChannelInitializer { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + private final SslProvider sslProvider; + private final X509Certificate[] trustedCertificates; + private final Supplier privateKeySupplier; + private final Supplier certificateSupplier; + + + public SslClientInitializer(SslProvider sslProvider) { + // null uses the system default trust store. + //Used for WebWhois, so we don't care about privateKey and certificates, setting them to null + this(sslProvider, null, null, null); + } + + public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, Supplier certificateSupplier) { + //We use the default trust store here as well, setting trustCertificates to null + this(sslProvider, null, privateKeySupplier, certificateSupplier); + } + + @VisibleForTesting + SslClientInitializer(SslProvider sslProvider, X509Certificate[] trustCertificates) { + this(sslProvider, trustCertificates, null, null); + } + + private SslClientInitializer( + SslProvider sslProvider, + X509Certificate[] trustCertificates, + Supplier privateKeySupplier, + Supplier certificateSupplier) { + logger.atInfo().log("Client SSL Provider: %s", sslProvider); + + this.sslProvider = sslProvider; + this.trustedCertificates = trustCertificates; + this.privateKeySupplier = privateKeySupplier; + this.certificateSupplier = certificateSupplier; + } + + @Override + protected void initChannel(C channel) throws Exception { + ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); + Protocol protocol = action.protocol(); + + //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate + checkNotNull(protocol, "Protocol is not set for channel: %s", channel); + SslContextBuilder sslContextBuilder = + SslContextBuilder.forClient() + .sslProvider(sslProvider) + .trustManager(trustedCertificates); + if (privateKeySupplier != null && certificateSupplier != null) + sslContextBuilder = sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get()); + + SslHandler sslHandler = sslContextBuilder + .build() + .newHandler(channel.alloc(), action.host(), protocol.port()); + + // Enable hostname verification. + SSLEngine sslEngine = sslHandler.engine(); + SSLParameters sslParameters = sslEngine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + sslEngine.setSSLParameters(sslParameters); + + channel.pipeline().addLast(sslHandler); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java new file mode 100644 index 00000000000..21010f0e887 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -0,0 +1,137 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; + +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; +import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpResponseStatus; +import java.net.MalformedURLException; +import java.net.URL; +import javax.inject.Inject; +import org.joda.time.Duration; + +/** + *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + * + *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection + * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

+ */ +public class WebWhoisActionHandler extends ActionHandler { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + @Inject + public WebWhoisActionHandler() {} + + + /** + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + */ + @Override + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) + throws ServerSideException { + + HttpResponseMessage response = (HttpResponseMessage) msg; + + + if (response.status() == HttpResponseStatus.OK) { + logger.atInfo().log("Received Successful HttpResponseStatus"); + + finished.setSuccess(); + + logger.atInfo().log("Response Received: " + response); + + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { + + //Obtain url to be redirected to + URL url; + try { + url = new URL(response.headers().get("Location")); + } catch (MalformedURLException e) { + //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it + throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + } + //From url, extract new host, port, and path + String newHost = url.getHost(); + String newPath = url.getPath(); + int newPort = url.getDefaultPort(); + + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); + + //Construct new Protocol to reflect redirected host, path, and port + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); + + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + + //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) + .build(); + + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + + //close this channel as we no longer need it + ChannelFuture future = ctx.close(); + future.addListener( + f -> { + logger.atInfo().log("Successfully Closed Connection"); + + //Once channel is closed, establish new connection to redirected host, and repeat same actions + ChannelFuture secondFuture = redirectedAction.call(); + + //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + secondFuture.addListener(f2 -> finished.setSuccess()); + + } + ); + } else { + //Add in metrics Handling that informs MetricsCollector the response was a FAILURE + finished.setSuccess(); + logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + + } + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 92e43501438..3fb8c187ad9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -19,31 +5,19 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import java.util.Arrays; -import javax.inject.Inject; -/** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. - * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a {@code - * name} method, which returns a standard name and the current hostname.

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, - ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + @Override @@ -52,38 +26,15 @@ public HttpRequestMessage setUri(String path) { return this; } - /** - * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} - */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } - - /** - * Modifies headers to reflect new host and new path if applicable. - */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) { - setUri(args[1]); - } - - return this; + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + ByteBuf buf = request.content(); + if (buf == null) { + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - throw new IllegalArgumentException( - String.format( - "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + Arrays.toString(args), args.length)); + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - } - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 7d2ff722076..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,21 +6,33 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} - */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { + super(version, status); + } + + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } - /** - * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} - */ - public HttpResponseMessage(FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); + + return finalResponse; } + + + } diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From 18393ffdeb1ccc98bc06e7b3511e134bc857e5ea Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:58:52 -0400 Subject: [PATCH 100/337] Fixed changes suggested by CydeWeys --- .../google/registry/cron/package-info.java | 2 +- .../google/registry/xml/package-info.java | 2 +- prober/build.gradle | 28 +-- .../handlers/WebWhoisActionHandlerTest.java | 221 ++++++++++++++++++ 4 files changed, 238 insertions(+), 15 deletions(-) create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java diff --git a/core/src/main/java/google/registry/cron/package-info.java b/core/src/main/java/google/registry/cron/package-info.java index 459f2513f93..49b18ca2885 100644 --- a/core/src/main/java/google/registry/cron/package-info.java +++ b/core/src/main/java/google/registry/cron/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/core/src/main/java/google/registry/xml/package-info.java b/core/src/main/java/google/registry/xml/package-info.java index f8e42585ecc..b3f27868b91 100644 --- a/core/src/main/java/google/registry/xml/package-info.java +++ b/core/src/main/java/google/registry/xml/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/prober/build.gradle b/prober/build.gradle index a277fb4f9f3..dbb7252a462 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -4,7 +4,7 @@ // 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 +// 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, @@ -12,23 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +apply plugin: 'java' + createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') dependencies { def deps = rootProject.dependencyMap - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java new file mode 100644 index 00000000000..63bb2cf5b53 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -0,0 +1,221 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelPromise; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ +@RunWith(JUnit4.class) +public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; + private static final int HTTPS_PORT = 443; + private static final String HTTP_REDIRECT = "http://"; + private static final String HTTPS_REDIRECT = "https://"; + private static final String REDIRECT_HOST = "www.example.com"; + private static final String REDIRECT_PATH = "/test/path"; + private static final String TARGET_HOST = "whois.nic.tld"; + private static final Duration DEFAULT_DURATION = new Duration(0L); + + + private EmbeddedChannel channel; + private ActionHandler actionHandler; + + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { + return Protocol.builder() + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); + } + + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); + } + + /** Sets up testing channel with requisite attributes */ + private void setupChannel(Protocol protocol) { + setupActionHandler(); + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); + } + + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); + } + + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); + } + + + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; + } + + + @Test + public void testSuccess_responseOk() { + //setup + Protocol initialProtocol = createProtocol("responseOk", 0, ""); + setupChannel(initialProtocol); + + //stores future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that we successfully receivved good response and protocol is unchanged + assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + } + + @Test + public void testSuccess_responseBad() { + //setup + Protocol initialProtocol = createProtocol("responseBad", 0, ""); + setupChannel(initialProtocol); + + //stores future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, but event is not success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + + //ensures Protocol is the same + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + } + + @Test + public void testSuccess_redirectCloseChannel() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); + + //stores future + ChannelFuture future = actionHandler.apply(outboundMessage); + + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + + + } + + @Test + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + + + channel.writeInbound(originalResponse); + + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); + + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + + + } + +} From ae9980c9ba4bd141f1f2c00f897fd76524ad8cd7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 101/337] Added missing license headers and JavaDoc --- .../handlers/ServerSideException.java | 16 ++++++- .../blackbox/messages/HttpRequestMessage.java | 45 ++++++++++++++----- .../messages/HttpResponseMessage.java | 32 ++++++++++--- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java index 5d3addb920e..441062a9e7b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; /** @@ -12,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 3fb8c187ad9..8fbb55c6339 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,13 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} + * (but needs to implement {@link OutboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion + * from {@link FullHttpRequest} to its type

+ */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +35,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,15 +42,22 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - if (buf == null) { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //creates message based on content found in original request + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //stores headers from request in finalRequest + request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); + + return finalRequest; + + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..776e7de0824 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,11 +1,33 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} + * (but needs to implement {@link InboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion + * from {@link FullHttpResponse} to its type

+ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -17,22 +39,20 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } + /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); + //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + //stores headers from response in finalResponse + response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); return finalResponse; } - - - } From 368e47d8bd50ad323c4a0e980402cd9ad9b8c278 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 102/337] Minor fix in NewChannelAction JavaDoc --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..1e7578d5679 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; - import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -28,8 +27,7 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) */ @AutoValue public abstract class NewChannelAction extends ProbingAction { From 532581fc5e04fb9a15b6f9a837ef3b81d7349bf1 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 13:33:23 -0400 Subject: [PATCH 103/337] Minor Style Fix --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 ---- .../java/google/registry/monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/handlers/WebWhoisActionHandler.java | 2 -- 3 files changed, 7 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..84cf75492f2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -52,7 +52,6 @@ public Channel channel() { return this.channel; } - @Override public abstract Builder toBuilder(); @@ -120,7 +119,6 @@ public static NewChannelAction.Builder builder() return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -129,6 +127,4 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index b0071ea4467..2a4a8d0ed76 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -55,4 +55,3 @@ public static abstract class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 21010f0e887..5b77461cd8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -131,7 +131,5 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } } - - } From cd9c51c3f9340d06b8ba92ad76ce925d842a3c07 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 104/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 40 +-- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 17 +- .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProberModule.java | 97 ++++--- .../monitoring/blackbox/ProbingAction.java | 17 +- .../monitoring/blackbox/ProbingSequence.java | 122 +++++++++ .../monitoring/blackbox/ProbingStep.java | 170 ++++++++++++ .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 12 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 ++++ .../monitoring/blackbox/WebWhoisModule.java | 216 ++++++--------- .../exceptions/EppClientException.java | 29 ++ .../exceptions/InternalException.java | 29 ++ .../exceptions/ResponseException.java | 29 ++ .../ServerSideException.java | 4 +- .../blackbox/handlers/ActionHandler.java | 71 +++-- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/WebWhoisActionHandler.java | 19 +- .../handlers/WebWhoisMessageHandler.java | 42 +-- .../blackbox/messages/HttpRequestMessage.java | 50 +--- .../messages/HttpResponseMessage.java | 32 +-- .../blackbox/ProbingActionTest.java | 173 ++++++------ .../blackbox/ProbingSequenceStepTest.java | 219 +++++++++++++++ .../blackbox/TestServers/TestServer.java | 85 ++++++ .../blackbox/TestServers/WebWhoisServer.java | 92 +++++++ .../monitoring/blackbox/TestUtils.java | 252 ++++++++++++++++++ .../monitoring/blackbox/TokenTest.java | 60 +++++ .../blackbox/handlers/ConversionHandler.java | 23 +- .../blackbox/handlers/NettyRule.java | 201 ++++++++++++++ .../handlers/SslClientInitializerTest.java | 233 ++++++++++++++++ .../handlers/SslInitializerTestUtils.java | 95 +++++++ .../blackbox/handlers/TestActionHandler.java | 19 +- .../handlers/WebWhoisActionHandlerTest.java | 222 ++++++++++----- 36 files changed, 2433 insertions(+), 498 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java diff --git a/prober/build.gradle b/prober/build.gradle index dbb7252a462..993da44655d 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,30 +16,36 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') + //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -48,3 +54,5 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 84cf75492f2..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -52,6 +53,7 @@ public Channel channel() { return this.channel; } + @Override public abstract Builder toBuilder(); @@ -83,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -116,9 +118,10 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } + @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -127,4 +130,6 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } + } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 333330207f1..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,16 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index df8b5fdbabd..73bd9127852 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,84 +14,99 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import io.netty.channel.Channel; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SslProvider; import java.util.Set; import javax.inject.Singleton; -import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and - * stores {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link - * ProbingSequence}. + * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} + * + *

Provides

*/ @Module public class ProberModule { + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; - /** - * Default {@link Duration} chosen to be time between each {@link ProbingAction} call. - */ - private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - - /** - * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. - */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** - * {@link Provides} one global {@link Channel} class that is used to construct a {@link - * io.netty.bootstrap.Bootstrap}. - */ @Provides - @Singleton - Class provideChannelClazz() { - return NioSocketChannel.class; + @HttpWhoisProtocol + ProbingSequence provideHttpWhoisSequence( + @HttpWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** - * {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. - */ @Provides - @Singleton - Duration provideDuration() { - return DEFAULT_DURATION; + @HttpsWhoisProtocol + ProbingSequence provideHttpsWhoisSequence( + @HttpsWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** - * {@link Provides} the {@link SslProvider} used by instances of {@link - * google.registry.monitoring.blackbox.handlers.SslClientInitializer} - */ @Provides - @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } - /** - * Root level {@link Component} that provides each {@link ProbingSequence}. - */ + @Provides + @HttpsWhoisProtocol + int provideHttpsWhoisPort() { + return httpsWhoIsPort; + } + + @Provides + ImmutableMap providePortToProtocolMap( + Set protocolSet) { + return Maps.uniqueIndex(protocolSet, Protocol::port); + } + + + @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, + TokenModule.class }) public interface ProberComponent { - //Standard WebWhois sequence - Set sequences(); + @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); + + @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); + + ImmutableMap providePortToProtocolMap(); + + @WebWhoisProtocol Token provideWebWhoisToken(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2441debb12d..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -34,7 +34,7 @@ import javax.inject.Provider; /** - *Superclass that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -183,4 +183,19 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + @Override + public String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n" + + "path: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host(), + path() + ); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java new file mode 100644 index 00000000000..6387207fea4 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -0,0 +1,122 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.EventLoopGroup; + +/** + * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * + * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} + * but for tests is {@link LocalChannel} + * + *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, + * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * + *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one + * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ */ +public class ProbingSequence { + private ProbingStep firstStep; + + /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ + private EventLoopGroup eventGroup; + + /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ + private Bootstrap bootstrap; + + public Bootstrap getBootstrap() { + return bootstrap; + } + + public void start(Token token) { + // calls the first step with input token; + firstStep.accept(token); + } + + /** + * {@link Builder} which takes in {@link ProbingStep}s + * + * @param Same specified {@code C} for overall {@link ProbingSequence} + */ + public static class Builder { + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstSequenceStep; + private EventLoopGroup eventLoopGroup; + private Class classType; + + Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; + return this; + } + + Builder addStep(ProbingStep step) { + if (currentStep == null) { + firstStep = step; + } else { + currentStep.nextStep(step); + } + currentStep = step; + return this; + } + + /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ + Builder makeFirstRepeated() { + firstSequenceStep = currentStep; + return this; + } + /** Set the class to be the same as {@code C} */ + public Builder setClass(Class classType) { + this.classType = classType; + return this; + } + + public ProbingSequence build() { + currentStep.nextStep(firstSequenceStep); + currentStep.lastStep(); + return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + } + + } + + /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ + private void setParents() { + ProbingStep currentStep = firstStep.parent(this).nextStep(); + + while (currentStep != firstStep) { + currentStep = currentStep.parent(this).nextStep(); + } + } + private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, + Class classType) { + this.firstStep = firstStep; + this.eventGroup = eventLoopGroup; + this.bootstrap = new Bootstrap() + .group(eventGroup) + .channel(classType); + setParents(); + } + + @Override + public String toString() { + return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); + + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java new file mode 100644 index 00000000000..5bad5abf6bf --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -0,0 +1,170 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.io.IOException; +import java.util.function.Consumer; +import org.joda.time.Duration; + +/** + * Represents generator of actions performed at each step in {@link ProbingSequence} + * + * @param See {@code C} in {@link ProbingSequence} + * + *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are + * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies + * these components on each loop iteration with the consumed {@link Token} and from that, + * generates new {@link ProbingAction} to perform<./p> + * + *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

+ */ +public abstract class ProbingStep implements Consumer { + + public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); + protected static final Duration DEFAULT_DURATION = new Duration(2000L); + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + protected LocalAddress address = DEFAULT_ADDRESS; + + /** Necessary boolean to inform when to obtain next {@link Token}*/ + private boolean isLastStep = false; + private ProbingStep nextStep; + private ProbingSequence parent; + + protected Duration duration; + + protected final Protocol protocol; + protected final OutboundMessageType message; + + protected ProbingStep(Protocol protocol, OutboundMessageType message) { + this.protocol = protocol; + this.message = message; + } + + private OutboundMessageType message() { + return message; + } + + Protocol protocol() { + return protocol; + } + + + void lastStep() { + isLastStep = true; + } + + void nextStep(ProbingStep step) { + this.nextStep = step; + } + + ProbingStep nextStep() { + return this.nextStep; + } + + ProbingStep parent(ProbingSequence parent) { + this.parent = parent; + return this; + } + + /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + private ProbingAction generateAction(Token token) throws InternalException { + ProbingAction generatedAction; + + OutboundMessageType message = token.modifyMessage(message()); + + //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction + if (protocol().persistentConnection() && token.channel() != null) { + generatedAction = ExistingChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .channel(token.channel()) + .build(); + } else { + generatedAction = NewChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .bootstrap(parent.getBootstrap()) + .address(address) + .build(); + + } + return generatedAction; + } + + + /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + private Token generateNextToken(Token token) { + return (isLastStep) ? token.next() : token; + } + + @Override + public void accept(Token token) { + ProbingAction nextAction; + //attempt to generate new action. On error, move on to next step + try { + nextAction = generateAction(token); + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Generation"); + nextStep.accept(generateNextToken(token)); + return; + } + + //If the next step maintains the connection, pass on the channel from this + if (protocol().persistentConnection()) { + token.channel(nextAction.channel()); + } + + //call the created action + ChannelFuture future = nextAction.call(); + + //On result, either log success and move on, or + future.addListener(f -> { + if (f.isSuccess()) { + logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); + nextStep.accept(generateNextToken(token)); + } else { + logger.atSevere().withCause(f.cause()).log("Did not result in future success"); + } + }); + } + + @Override + public String toString() { + return String.format("ProbingStep with Protocol: %s\n" + + "OutboundMessage: %s\n" + + "and parent sequence: %s", + protocol(), + message(), + parent); + } + +} + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 2a4a8d0ed76..855d9c5b41a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -54,4 +54,16 @@ public static abstract class Builder { public abstract Protocol build(); } + + @Override + public String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 55fc7cf71a9..dba905c0e49 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,120 +18,90 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; + +import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.time.Duration; -/** - * A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. - */ +/** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; - private static final String HTTP_PROTOCOL_NAME = "http"; - private static final String HTTPS_PROTOCOL_NAME = "https"; - - /** - * Standard length of messages used by Proxy. Equates to 0.5 MB. - */ - private static final int maximumMessageLengthBytes = 512 * 1024; + final static String DOMAIN_SUFFIX = "whois.nic."; - /** - * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. - */ + /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpWhoisProtocol { + @interface HttpWhoisProtocol {} - } + /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ + @Qualifier + @interface HttpsWhoisProtocol {} - /** - * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. - */ + /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier - public @interface HttpsWhoisProtocol { + public @interface WebWhoisProtocol {} - } - /** - * Dagger qualifier to provide any WebWhois related bindings. - */ - @Qualifier - public @interface WebWhoisProtocol { - } + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + - /** - * {@link Provides} standard WebWhois sequence. - */ @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { + @HttpWhoisProtocol + static ProbingStep provideHttpWhoisProbingSequence( + @HttpWhoisProtocol Protocol httpWhoisProtocol) { + return new ProbingStepWeb<>(httpWhoisProtocol); + } - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); + @Provides + @HttpsWhoisProtocol + static ProbingStep provideHttpsWhoisProbingStep( + @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { + return new ProbingStepWeb<>(httpsWhoisProtocol); } - /** - * {@link Provides} only step used in WebWhois sequence. - */ + @Singleton @Provides - @WebWhoisProtocol - static ProbingStep provideWebWhoisStep( - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @WebWhoisProtocol Bootstrap bootstrap, - HttpRequestMessage messageTemplate, - Duration duration) { - - return ProbingStep.builder() - .setProtocol(httpWhoisProtocol) - .setBootstrap(bootstrap) - .setMessageTemplate(messageTemplate) - .setDuration(duration) + @HttpWhoisProtocol + static Protocol provideHttpWhoisProtocol( + @HttpWhoisProtocol int httpWhoisPort, + @HttpWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** - * {@link Provides} the {@link Protocol} that corresponds to http connection. - */ @Singleton @Provides - @HttpWhoisProtocol - static Protocol provideHttpWhoisProtocol( + @IntoSet + static Protocol provideHttpProtocolForSet( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTP_PROTOCOL_NAME) - .setPort(httpWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** - * {@link Provides} the {@link Protocol} that corresponds to https connection. - */ + @Singleton @Provides @HttpsWhoisProtocol @@ -139,24 +109,40 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTPS_PROTOCOL_NAME) - .setPort(httpsWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } + @Singleton + @Provides + @IntoSet + static Protocol provideHttpsProtocolForSet( + @HttpsWhoisProtocol int httpsWhoisPort, + @HttpsWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Provides + @WebWhoisProtocol + String provideHttpWhoisHost() { + return "app"; + } + - /** - * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http - * protocol. - */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -165,18 +151,13 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** - * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https - * protocol. - */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( - @HttpsWhoisProtocol - Provider> sslClientInitializerProvider, + @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -186,67 +167,34 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } - @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); - } - - @Provides - static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { - return new HttpObjectAggregator(maxContentLength); - } - - /** - * {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. - */ - @Provides - @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer( - SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); - } - /** - * {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. - */ - @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap( - EventLoopGroup eventLoopGroup, - Class channelClazz) { - return new Bootstrap() - .group(eventLoopGroup) - .channel(channelClazz); + static MessageHandler provideMessageHandler() { + return new WebWhoisMessageHandler(); } @Provides - @WebWhoisProtocol - int provideMaximumMessageLengthBytes() { - return maximumMessageLengthBytes; + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); } - /** - * {@link Provides} the list of top level domains to be probed - */ - @Singleton @Provides - @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy", "xn--q9jyb4c"); + static HttpObjectAggregator provideHttpObjectAggregator() { + return new HttpObjectAggregator(1048576); } @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return HTTP_WHOIS_PORT; + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } @Provides @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return HTTPS_WHOIS_PORT; + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index dfd88cba1ce..c3622e1b810 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,32 +15,45 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; /** - *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + * Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, + * as it should only be passed in messages that implement the {@link InboundMessageType} interface. * - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} - * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception - * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses - * specify further work to be done for specific kinds of channel pipelines.

+ *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link + * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. + * Second, it stores the {@link OutboundMessageType} passed down the pipeline, so that subclasses + * can use that information for their own processes. Lastly, with any exception thrown, the + * connection is closed, and the ProbingAction governing this channel is informed of the error. + * Subclasses specify further work to be done for specific kinds of channel pipelines. */ public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Three types of responses received down pipeline */ + public enum ResponseType {SUCCESS, FAILURE, ERROR} + + /** Status of response for current {@link ActionHandler} instance */ + private static ResponseType status; + protected ChannelPromise finished; - /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** + * Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized + * {@link ChannelPromise} + */ public ChannelFuture getFuture() { return finished; } @@ -48,25 +61,47 @@ public ChannelFuture getFuture() { /** Initializes new {@link ChannelPromise} */ @Override public void handlerAdded(ChannelHandlerContext ctx) { - //Once handler is added to channel pipeline, initialize channel and future for this handler + // Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws Exception { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { //simply marks finished as success + status = ResponseType.SUCCESS; finished.setSuccess(); } - /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ + /** + * Logs the channel and pipeline that caused error, closes channel, then informs {@link + * ProbingAction} listeners of error + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); + logger.atSevere().withCause(cause).log( + String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), ctx.channel().pipeline().toString())); + + + if (ResponseException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + status = ResponseType.FAILURE; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (ServerSideException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + status = ResponseType.ERROR; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (InternalException.class.isInstance(cause)){ + logger.atSevere().withCause(cause).log("Severe internal error"); + finished.setFailure(cause); + } else { + finished.setFailure(cause); + } - finished.setFailure(cause); + //due to failure, close channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 5b77461cd8f..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -17,20 +17,16 @@ import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; @@ -59,7 +55,7 @@ public WebWhoisActionHandler() {} */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ServerSideException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -67,9 +63,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - finished.setSuccess(); - logger.atInfo().log("Response Received: " + response); + super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -79,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -126,10 +121,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + throw new ResponseException("Response received from remote site was: " + response.status()); } } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 576d6a04d42..4afc5d95ba7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,59 +1,33 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -/** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom - * type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for - * redirection. - */ -public class WebWhoisMessageHandler extends ChannelDuplexHandler { +public class WebWhoisMessageHandler extends MessageHandler { + + private HttpRequestMessage request; @Inject - public WebWhoisMessageHandler() { - } + public WebWhoisMessageHandler() {} - /** - * Retains {@link HttpRequestMessage} and calls super write method. - */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) - throws Exception { - HttpRequestMessage request = (HttpRequestMessage) msg; + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** - * Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link - * InboundMessageType} instance. - */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + FullHttpResponse originalResponse = (FullHttpResponse) msg; - HttpResponseMessage response = new HttpResponseMessage(originalResponse); + InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8fbb55c6339..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,13 +6,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} - * (but needs to implement {@link OutboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion - * from {@link FullHttpRequest} to its type

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -35,6 +14,11 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + + @Override public HttpRequestMessage setUri(String path) { @@ -42,22 +26,16 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - - //creates message based on content found in original request - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - - - //stores headers from request in finalRequest - request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - - return finalRequest; - + HttpRequestMessage output; + if (buf == null) { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + } else { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + } + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 776e7de0824..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,33 +1,11 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} - * (but needs to implement {@link InboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion - * from {@link FullHttpResponse} to its type

- */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -39,20 +17,22 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } - /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); - //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - //stores headers from response in finalResponse - response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); return finalResponse; } + + + } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index 6cfb235d97c..cbcf2fc82b0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,19 +15,20 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -38,85 +39,111 @@ import io.netty.channel.nio.NioEventLoopGroup; import javax.inject.Provider; import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; - /** * Unit tests for {@link ProbingAction} subtypes * *

Attempts to test how well each {@link ProbingAction} works with an {@link ActionHandler} * subtype when receiving to all possible types of responses

- */ + * */ @RunWith(JUnit4.class) public class ProbingActionTest { - - private static final String TEST_MESSAGE = "MESSAGE_TEST"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final int TEST_PORT = 0; - - private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - - /** - * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on - * {@link ProbingAction} - */ + /** Necessary Constants for test */ + private final String TEST_MESSAGE = "MESSAGE_TEST"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final int TEST_PORT = 0; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = () -> testHandler; - private Provider conversionHandlerProvider = () -> conversionHandler; + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - /** - * Used for testing how well probing step can create connection to blackbox server - */ + private ProbingAction newChannelAction; + private ProbingAction existingChannelAction; + private EmbeddedChannel channel; + private Protocol protocol; + + /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); + /** Sets up a {@link Protocol} corresponding to when a new connection is created */ + private void setupNewChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(false) + .build(); + } + /** Sets up a {@link Protocol} corresponding to when a new connection exists */ + private void setupExistingChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(true) + .build(); + } + + /** Sets up a {@link NewChannelAction} with test specified attributes */ + private void setupNewChannelAction() { + newChannelAction = NewChannelAction.builder() + .bootstrap(bootstrap) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .address(address) + .build(); + } + + private void setupChannel() { + channel = new EmbeddedChannel(); + } + + /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + private void setupExistingChannelAction(Channel channel) { + existingChannelAction = ExistingChannelAction.builder() + .channel(channel) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .build(); + } - @Ignore @Test public void testBehavior_existingChannel() { //setup - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up a Protocol corresponding to when a connection exists. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(true) - .build(); + setupChannel(); + setupExistingChannelProtocol(); + setupExistingChannelAction(channel); + channel.pipeline().addLast(conversionHandler); + channel.pipeline().addLast(testHandler); - // Sets up a ProbingAction that creates a channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setChannel(channel) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost("") - .build(); - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = existingChannelAction.call(); - //Obtains the outboundMessage passed through pipeline after delay - Object msg = null; - while (msg == null) { - msg = channel.readOutbound(); - } - //tests the passed message is exactly what we expect + //Ensures that we pass in the right message to the channel and haven't marked the future as success yet + Object msg = channel.readOutbound(); assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - assertThat(request).isEqualTo(TEST_MESSAGE); - - // Ensures that we haven't marked future as done until response is received. - assertThat(future.isDone()).isFalse(); + String response = ((ByteBuf) msg).toString(UTF_8); + assertThat(response).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()).isFalse(); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); @@ -128,41 +155,19 @@ public void testBehavior_existingChannel() { @Test public void testSuccess_newChannel() throws Exception { //setup - - LocalAddress address = new LocalAddress(ADDRESS_NAME); - Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); - - // Sets up a Protocol corresponding to when a new connection is created. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - + setupNewChannelProtocol(); + setupNewChannelAction(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - // Sets up a ProbingAction with existing channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future = future.syncUninterruptibly(); + future.sync(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler) testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()); + assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java new file mode 100644 index 00000000000..7a713017072 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java @@ -0,0 +1,219 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.TestUtils.TestStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.handlers.ConversionHandler; +import google.registry.monitoring.blackbox.handlers.NettyRule; +import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.junit.Rule; +import org.junit.Test; + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + + /** Used for testing how well probing step can create connection to blackbox server */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + + + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ + private ProbingSequence testSequence; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); + dummyStep = new DummyStep(testProtocol, eventLoopGroup); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(false) + .build(); + } + + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(true) + .build(); + } + + /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ + private void setupSequence() { + testSequence = new ProbingSequence.Builder() + .eventLoopGroup(eventLoopGroup) + .setClass(LocalChannel.class) + .addStep(firstStep) + .makeFirstRepeated() + .addStep(dummyStep) + .build(); + } + + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //there should be no next step + assertThat(firstStep.nextStep()).isNull(); + + //we expect that this exception be thrown + assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); + + } + + @Test + public void testWithSequence_NewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupSequence(); + setupNewChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupSequence(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java new file mode 100644 index 00000000000..67e2cb7165d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -0,0 +1,85 @@ +package google.registry.monitoring.blackbox.TestServers; + +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; + +/** + * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + */ +public abstract class TestServer { + private LocalAddress localAddress; + + TestServer(LocalAddress localAddress, ImmutableList handlers) { + this(new NioEventLoopGroup(1), localAddress, handlers); + } + + TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + this.localAddress = localAddress; + + //Creates ChannelInitializer with handlers specified + ChannelInitializer serverInitializer = new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) { + for (ChannelHandler handler : handlers) { + ch.pipeline().addLast(handler); + } + } + }; + //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using LocalServerChannel class + ServerBootstrap serverBootstrap = + new ServerBootstrap() + .group(eventLoopGroup) + .channel(LocalServerChannel.class) + .childHandler(serverInitializer); + + ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); + + } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** Saves any inbound error as the cause of the promise failure. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java new file mode 100644 index 00000000000..ab9997b6c68 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -0,0 +1,92 @@ +package google.registry.monitoring.blackbox.TestServers; + +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpServerCodec; + +/** + * {@link TestServer} subtype that performs WebWhois Services Expected + * + * It will either redirect the client to the correct location if given the + * requisite redirect input, give the client a successful response if they give + * the expected final destination, or give the client an error message if given + * an unexpected host location + */ +public class WebWhoisServer extends TestServer { + + public WebWhoisServer(LocalAddress localAddress, ImmutableList handlers) { + super(localAddress, handlers); + } + + public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + super(eventLoopGroup, localAddress, handlers); + } + + /** Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the HttpRequestMessage object through pipeline */ + public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + return new WebWhoisServer( + eventLoopGroup, + localAddress, + ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) + ); + } + /** Creates server that sends exactly what we expect a remote server to send as a response, by sending the {@link ByteBuf} of the response through pipeline */ + public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + return new WebWhoisServer( + eventLoopGroup, + localAddress, + ImmutableList.of( + new HttpServerCodec(), + new HttpObjectAggregator(1048576), + new RedirectHandler(redirectInput, destinationInput)) + ); + } + + /** + * Handler that will wither redirect client, give successful response, or give error messge + */ + @Sharable + static class RedirectHandler extends ChannelDuplexHandler { + private String redirectInput; + private String destinationInput; + + /** + * + * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + */ + public RedirectHandler(String redirectInput, String destinationInput) { + this.redirectInput = redirectInput; + this.destinationInput = destinationInput; + } + + /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + HttpRequest request = (HttpRequest) msg; + HttpResponse response; + if (request.headers().get("host").equals(redirectInput)) { + response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + } else if (request.headers().get("host").equals(destinationInput)) { + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + } else { + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + } + ctx.channel().writeAndFlush(response); + + } + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java new file mode 100644 index 00000000000..8d1722c9625 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -0,0 +1,252 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.US_ASCII; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.joda.time.Duration; + +/** Utility class for various helper methods used in testing. */ +public class TestUtils { + + static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + + public static FullHttpRequest makeHttpGetRequest(String host, String path) { + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); + request.headers().set("host", host).setInt("content-length", 0); + return request; + } + + public static FullHttpResponse makeHttpResponse(String content, HttpResponseStatus status) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buf); + response.headers().setInt("content-length", buf.readableBytes()); + return response; + } + + public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status); + response.headers().setInt("content-length", 0); + return response; + } + + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + public static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; + } + + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); + return response; + } + + /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ + public static class TestProvider implements Provider { + + private E obj; + + public TestProvider(E obj) { + this.obj = obj; + } + + @Override + public E get() { + return obj; + } + } + + /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ + public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { + + String message; + + public DuplexMessageTest() { + message = ""; + } + + public DuplexMessageTest(String msg) { + message = msg; + } + + @Override + public String toString() { + return message; + } + } + + /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ + public static class TestStep extends ProbingStep { + + public TestStep(Protocol protocol, String testMessage, LocalAddress address) { + super(protocol, new DuplexMessageTest(testMessage)); + this.address = address; + this.duration = Duration.ZERO; + } + } + + /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ + public static class DummyStep extends ProbingStep { + private DefaultPromise future; + + public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { + super(protocol, new DuplexMessageTest()); + future = new DefaultPromise(eventLoopGroup.next()) {}; + duration = Duration.ZERO; + } + + @Override + public void accept(Token token) { + future.setSuccess(token); + } + public DefaultPromise getFuture() { + return future; + } + } + + /** Basic outline for {@link Token} instances to be used in tests */ + private static abstract class TestToken extends Token { + private String host; + + protected TestToken(String host) { + this.host = host; + } + @Override + public Token next() { + return this; + } + + @Override + public OutboundMessageType modifyMessage(OutboundMessageType message) { + return message; + } + + @Override + public String getHost() { + return host; + } + + } + + /** {@link TestToken} instance that creates new channel */ + public static class NewChannelToken extends TestToken { + public NewChannelToken(String host) { + super(host); + } + @Override + public Channel channel() { + return null; + } + } + + /** {@link TestToken} instance that passes in existing channel */ + public static class ExistingChannelToken extends TestToken { + private Channel channel; + + public ExistingChannelToken(Channel channel, String host) { + super(host); + this.channel = channel; + } + @Override + public Channel channel() { + return channel; + } + } + + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java new file mode 100644 index 00000000000..ef5cba5b60d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -0,0 +1,60 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + */ +@RunWith(JUnit4.class) +public class TokenTest { + + private static String PREFIX = "whois.nic."; + private static String TEST_STARTER = "starter"; + private static String TEST_DOMAIN = "test"; + + public Token webToken = new WebWhoisToken(TEST_DOMAIN); + + @Test + public void testWebToken_MessageModificationSuccess() { + //creates Request message with header + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + message.headers().set("host", TEST_STARTER); + + //attempts to use Token's method for modifying the method based on its stored host + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { + throw new RuntimeException(e); + } + + + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 987abbfd7dc..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,38 +17,31 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link - * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to + * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** - * Handles inbound conversion - */ + /** Handles inbound conversion */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } - /** - * Handles outbound conversion - */ + /** Handles outbound conversion */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java new file mode 100644 index 00000000000..b6b5e8fbe0c --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -0,0 +1,201 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.truth.Truth.assertThat; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.truth.ThrowableSubject; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.ReferenceCountUtil; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import org.junit.rules.ExternalResource; + +/** + * Helper for setting up and testing client / server connection with netty. + * + *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ */ +public final class NettyRule extends ExternalResource { + + + + // All I/O operations are done inside the single thread within this event loop group, which is + // different from the main test thread. Therefore synchronizations are required to make sure that + // certain I/O activities are finished when assertions are performed. + public NettyRule() { + eventLoopGroup = new NioEventLoopGroup(1); + } + public NettyRule(EventLoopGroup e) { + eventLoopGroup = e; + } + private final EventLoopGroup eventLoopGroup; + private WebWhoisServer webWhoisServer; + + // Handler attached to server's channel to record the request received. + private EchoHandler echoHandler; + + // Handler attached to client's channel to record the response received. + private DumpHandler dumpHandler; + + private Channel channel; + + /** Sets up a server channel bound to the given local address. */ + public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + checkState(echoHandler == null, "Can't call setUpServer twice"); + echoHandler = new EchoHandler(); + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + } + + /** Sets up a client channel connecting to the give local address. */ + void setUpClient( + LocalAddress localAddress, + ProbingAction probingAction, + ChannelHandler handler) { + checkState(echoHandler != null, "Must call setUpServer before setUpClient"); + checkState(dumpHandler == null, "Can't call setUpClient twice"); + dumpHandler = new DumpHandler(); + ChannelInitializer clientInitializer = + new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) throws Exception { + // Add the given handler + ch.pipeline().addLast(handler); + // Add the "dumpHandler" last to log the incoming message + ch.pipeline().addLast(dumpHandler); + } + }; + Bootstrap b = + new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class) + .handler(clientInitializer) + .attr(PROBING_ACTION_KEY, probingAction); + channel = b.connect(localAddress).syncUninterruptibly().channel(); + } + + private void checkReady() { + checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); + } + + /** Test that custom setup to send message to current server sends right message */ + public void assertThatCustomWorks(String message) throws Exception { + assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); + + } + + /** + * Test that a message can go through, both inbound and outbound. + * + *

The client writes the message to the server, which echos it back and saves the string in its + * promise. The client receives the echo and saves it in its promise. All these activities happens + * in the I/O thread, and this call itself returns immediately. + */ + void assertThatMessagesWork() throws Exception { + checkReady(); + assertThat(channel.isActive()).isTrue(); + + writeToChannelAndFlush(channel, "Hello, world!"); + assertThat(echoHandler.getRequestFuture().get()).isEqualTo("Hello, world!"); + assertThat(dumpHandler.getResponseFuture().get()).isEqualTo("Hello, world!"); + } + + Channel getChannel() { + checkReady(); + return channel; + } + + ThrowableSubject assertThatServerRootCause() { + checkReady(); + return assertThat( + Throwables.getRootCause( + assertThrows(ExecutionException.class, () -> echoHandler.getRequestFuture().get()))); + } + + ThrowableSubject assertThatClientRootCause() { + checkReady(); + return assertThat( + Throwables.getRootCause( + assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); + } + + + + /** A handler that dumps its inbound message to a promise that can be inspected later. */ + private static class DumpHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture responseFuture = new CompletableFuture<>(); + + Future getResponseFuture() { + return responseFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + assertThat(msg).isInstanceOf(ByteBuf.class); + String response = ((ByteBuf) msg).toString(UTF_8); + // There is no more use of this message, we should release its reference count so that it + // can be more effectively garbage collected by Netty. + ReferenceCountUtil.release(msg); + // Save the string in the promise and make it as complete. + responseFuture.complete(response); + } + + /** Saves any inbound error into the failure cause of the promise. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); + } + } + + @Override + protected void after() { + Future unusedFuture = eventLoopGroup.shutdownGracefully(); + } + + private static void writeToChannelAndFlush(Channel channel, String data) { + ChannelFuture unusedFuture = + channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java new file mode 100644 index 00000000000..469c62a8f75 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -0,0 +1,233 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; +import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; +import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.ExistingChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SniHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslProvider; +import io.netty.handler.ssl.util.SelfSignedCertificate; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.cert.CertPathBuilderException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLException; +import org.joda.time.Duration; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +/** + * Unit tests for {@link SslClientInitializer}. + * + *

To validate that the handler accepts & rejects connections as expected, a test server and a + * test client are spun up, and both connect to the {@link LocalAddress} within the JVM. This avoids + * the overhead of routing traffic through the network layer, even if it were to go through + * loopback. It also alleviates the need to pick a free port to use. + * + *

The local addresses used in each test method must to be different, otherwise tests run in + * parallel may interfere with each other. + */ +@RunWith(Parameterized.class) +public class SslClientInitializerTest { + + private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); + + /** Fake host to test if the SSL engine gets the correct peer host. */ + private static final String SSL_HOST = "www.example.tld"; + + /** Fake port to test if the SSL engine gets the correct peer port. */ + private static final int SSL_PORT = 12345; + + @Rule + public NettyRule nettyRule = new NettyRule(); + + @Parameter(0) + public SslProvider sslProvider; + + // We do our best effort to test all available SSL providers. + @Parameters(name = "{0}") + public static SslProvider[] data() { + return OpenSsl.isAvailable() + ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[] {SslProvider.JDK}; + } + + /** Saves the SNI hostname received by the server, if sent by the client. */ + private String sniHostReceived; + + /** Fake protocol saved in channel attribute. */ + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .persistentConnection(false) + .build(); + + private ProbingAction probingAction; + + private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) + throws Exception { + SslContext sslContext = SslContextBuilder.forServer(privateKey, certificate).build(); + return new SniHandler( + hostname -> { + sniHostReceived = hostname; + return sslContext; + }); + } + + private void setupProbingAction(Channel channel) { + probingAction = ExistingChannelAction.builder() + .delay(Duration.ZERO) + .host(SSL_HOST) + .channel(channel) + .outboundMessage(DEFAULT_MESSAGE) + .protocol(PROTOCOL) + .build(); + } + + @Test + public void testSuccess_swappedInitializerWithSslHandler() throws Exception { + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider); + EmbeddedChannel channel = new EmbeddedChannel(); + setupProbingAction(channel); + channel.attr(PROBING_ACTION_KEY).set(probingAction); + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(sslClientInitializer); + ChannelHandler firstHandler = pipeline.first(); + assertThat(firstHandler.getClass()).isEqualTo(SslHandler.class); + SslHandler sslHandler = (SslHandler) firstHandler; + assertThat(sslHandler.engine().getPeerHost()).isEqualTo(SSL_HOST); + assertThat(sslHandler.engine().getPeerPort()).isEqualTo(SSL_PORT); + assertThat(channel.isActive()).isTrue(); + } + + @Test + public void testSuccess_protocolAttributeNotSet() { + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider); + EmbeddedChannel channel = new EmbeddedChannel(); + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(sslClientInitializer); + // Channel initializer swallows error thrown, and closes the connection. + assertThat(channel.isActive()).isFalse(); + } + + @Test + public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Exception { + SelfSignedCertificate ssc = new SelfSignedCertificate(SSL_HOST); + LocalAddress localAddress = + new LocalAddress("DEFAULT_TRUST_MANAGER_REJECT_SELF_SIGNED_CERT_" + sslProvider); + nettyRule.setUpServer(localAddress, getServerHandler(ssc.key(), ssc.cert())); + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider); + + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + // The connection is now terminated, both the client side and the server side should get + // exceptions. + nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); + nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); + assertThat(nettyRule.getChannel().isActive()).isFalse(); + } + + @Test + public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws Exception { + LocalAddress localAddress = + new LocalAddress("CUSTOM_TRUST_MANAGER_ACCEPT_CERT_SIGNED_BY_TRUSTED_CA_" + sslProvider); + + // Generate a new key pair. + KeyPair keyPair = getKeyPair(); + + // Generate a self signed certificate, and use it to sign the key pair. + SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Certificate cert = signKeyPair(ssc, keyPair, SSL_HOST); + + // Set up the server to use the signed cert and private key to perform handshake; + PrivateKey privateKey = keyPair.getPrivate(); + nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); + + // Set up the client to trust the self signed cert used to sign the cert that server provides. + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + + setUpSslChannel(nettyRule.getChannel(), cert); + nettyRule.assertThatMessagesWork(); + + // Verify that the SNI extension is sent during handshake. + assertThat(sniHostReceived).isEqualTo(SSL_HOST); + } + + @Test + public void testFailure_customTrustManager_wrongHostnameInCertificate() throws Exception { + LocalAddress localAddress = + new LocalAddress("CUSTOM_TRUST_MANAGER_WRONG_HOSTNAME_" + sslProvider); + + // Generate a new key pair. + KeyPair keyPair = getKeyPair(); + + // Generate a self signed certificate, and use it to sign the key pair. + SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Certificate cert = signKeyPair(ssc, keyPair, "wrong.com"); + + // Set up the server to use the signed cert and private key to perform handshake; + PrivateKey privateKey = keyPair.getPrivate(); + nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); + + // Set up the client to trust the self signed cert used to sign the cert that server provides. + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + + // When the client rejects the server cert due to wrong hostname, both the client and server + // should throw exceptions. + nettyRule.assertThatClientRootCause().isInstanceOf(CertificateException.class); + nettyRule.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST); + nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); + assertThat(nettyRule.getChannel().isActive()).isFalse(); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java new file mode 100644 index 00000000000..68b2919141d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java @@ -0,0 +1,95 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.truth.Truth.assertThat; + +import io.netty.channel.Channel; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.util.SelfSignedCertificate; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import javax.net.ssl.SSLSession; +import javax.security.auth.x500.X500Principal; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.x509.X509V3CertificateGenerator; + +/** + * Utility class that provides methods used by {@link SslClientInitializerTest} + */ +public class SslInitializerTestUtils { + + static { + Security.addProvider(new BouncyCastleProvider()); + } + + public static KeyPair getKeyPair() throws Exception { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); + keyPairGenerator.initialize(2048, new SecureRandom()); + return keyPairGenerator.generateKeyPair(); + } + + /** + * Signs the given key pair with the given self signed certificate. + * + * @return signed public key (of the key pair) certificate + */ + public static X509Certificate signKeyPair( + SelfSignedCertificate ssc, KeyPair keyPair, String hostname) throws Exception { + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + X500Principal dnName = new X500Principal("CN=" + hostname); + certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); + certGen.setSubjectDN(dnName); + certGen.setIssuerDN(ssc.cert().getSubjectX500Principal()); + certGen.setNotBefore(Date.from(Instant.now().minus(Duration.ofDays(1)))); + certGen.setNotAfter(Date.from(Instant.now().plus(Duration.ofDays(1)))); + certGen.setPublicKey(keyPair.getPublic()); + certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); + return certGen.generate(ssc.key(), "BC"); + } + + /** + * Verifies tha the SSL channel is established as expected, and also sends a message to the server + * and verifies if it is echoed back correctly. + * + * @param certs The certificate that the server should provide. + * @return The SSL session in current channel, can be used for further validation. + */ + static SSLSession setUpSslChannel( + Channel channel, + X509Certificate... certs) + throws Exception { + SslHandler sslHandler = channel.pipeline().get(SslHandler.class); + // Wait till the handshake is complete. + sslHandler.handshakeFuture().get(); + + assertThat(channel.isActive()).isTrue(); + assertThat(sslHandler.handshakeFuture().isSuccess()).isTrue(); + assertThat(sslHandler.engine().getSession().isValid()).isTrue(); + assertThat(sslHandler.engine().getSession().getPeerCertificates()) + .asList() + .containsExactlyElementsIn(certs); + // Returns the SSL session for further assertion. + return sslHandler.engine().getSession(); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 19e608c97d2..518bb9ba686 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,27 +14,26 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; /** - * Concrete implementation of {@link ActionHandler} that does nothing different from parent class - * other than store and return the {@code inboundMessage} + * Concrete implementation of {@link ActionHandler} that does nothing different from + * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ - private InboundMessageType receivedMessage; + private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage; + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } - public InboundMessageType getResponse() { + @Override + public String toString() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 63bb2cf5b53..71d8d66b6c0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,32 +15,45 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; +import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ +/** + * Unit tests for {@link WebWhoisActionHandler}. + * + *

Attempts to test how well {@link WebWhoisActionHandler} works + * when responding to all possible types of responses

+ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; @@ -50,80 +63,85 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; + private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); + private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - + private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; + private ProbingAction probingAction; + private Provider actionHandlerProvider; + private void generateLocalAddress() { + address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + } /** Creates default protocol with empty list of handlers and specified other inputs */ private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() .name(name) .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); + .handlerProviders(ImmutableList.of(actionHandlerProvider)) + .persistentConnection(false) + .build(); } /** Initializes new WebWhoisActionHandler */ private void setupActionHandler() { actionHandler = new WebWhoisActionHandler(); + actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); + private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + setupProbingActionBasic( + protocol, + outboundMessage, + makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); } + private Bootstrap makeBootstrap(EventLoopGroup group) { + return new Bootstrap() + .group(group) + .channel(LocalChannel.class); + } /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() + private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + probingAction = NewChannelAction.builder() .protocol(protocol) .outboundMessage(outboundMessage) .delay(DEFAULT_DURATION) .bootstrap(bootstrap) + .host(TARGET_HOST) + .address(DEFAULT_ADDRESS) .build(); } - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); + private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(host) + .address(address) + .build(); } - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; + private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testSuccess_responseOk() { + public void testBasic_responseOk() throws Exception { //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); - + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); @@ -146,10 +164,13 @@ public void testSuccess_responseOk() { } @Test - public void testSuccess_responseBad() { + public void testBasic_responseFailure() { //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseBad", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); @@ -158,7 +179,8 @@ public void testSuccess_responseBad() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + FullHttpResponse response = HttpResponseMessage + .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -172,19 +194,57 @@ public void testSuccess_responseBad() { //ensures Protocol is the same assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } + @Test + public void testBasic_responseError() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseError", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + + //stores future + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, and event is success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + } @Test - public void testSuccess_redirectCloseChannel() { + public void testBasic_redirectCloseChannel() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); + HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", 0); + generateLocalAddress(); + setupChannel(initialProtocol, outboundMessage); //stores future ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + //checks that future has not been set to successful or a failure + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); @@ -195,27 +255,69 @@ public void testSuccess_redirectCloseChannel() { } @Test - public void testSuccess_redirectHost() { + public void testBasic_redirectHost() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); channel.writeInbound(originalResponse); + ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); + Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); + assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); + } + + @Test + public void testAdvanced_responseOk() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", TARGET_HOST, group); + //stores future + ChannelFuture future = probingAction.call(); + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + } + + @Test + public void testAdvanced_responseFailure() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", TARGET_HOST, group); + + //stores future + ChannelFuture future = probingAction.call(); + + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } } + From 3f32f7b45d2493bc7ab193696f639d1a6b36f969 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 105/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 +++++++++----- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/ProbingSequence.java | 1 - .../monitoring/blackbox/ProbingStep.java | 7 +--- .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 - .../monitoring/blackbox/Tokens/Token.java | 4 +- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../monitoring/blackbox/WebWhoisModule.java | 2 +- .../exceptions/EppClientException.java | 29 ------------- .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++- .../handlers/WebWhoisMessageHandler.java | 22 +++++++++- .../blackbox/messages/HttpRequestMessage.java | 41 +++++++++++++------ .../messages/HttpResponseMessage.java | 26 ++++++++---- .../blackbox/messages/InboundMessageType.java | 1 - .../messages/OutboundMessageType.java | 1 - .../blackbox/TestServers/TestServer.java | 16 +++++++- .../blackbox/TestServers/WebWhoisServer.java | 18 +++++++- 20 files changed, 145 insertions(+), 86 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6387207fea4..2eb90a1d6c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -119,4 +119,3 @@ public String toString() { } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 5bad5abf6bf..80b04a3d0c9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.exceptions.EppClientException; import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; import io.netty.channel.local.LocalAddress; -import java.io.IOException; + import java.util.function.Consumer; import org.joda.time.Duration; @@ -164,7 +162,4 @@ public String toString() { message(), parent); } - } - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 855d9c5b41a..0fc3a3e09c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -66,4 +66,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dba905c0e49..7200a1877e2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -197,4 +197,4 @@ static SslClientInitializer provideSslClientInitializer(SslPro } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 4afc5d95ba7..0acf223eb9e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; @@ -8,6 +22,11 @@ import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; +/** + * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} + * in case of reuse for redirection + */ public class WebWhoisMessageHandler extends MessageHandler { private HttpRequestMessage request; @@ -15,6 +34,7 @@ public class WebWhoisMessageHandler extends MessageHandler { @Inject public WebWhoisMessageHandler() {} + /** Retains {@link HttpRequestMessage} and calls super write method*/ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { request = (HttpRequestMessage) msg; @@ -23,9 +43,9 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) } + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - FullHttpResponse originalResponse = (FullHttpResponse) msg; InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..b06938d80a1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +31,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,16 +38,19 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + + request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + + return finalRequest; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..283b14440ac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,7 +33,7 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); @@ -26,13 +43,8 @@ public static HttpResponseMessage fromResponse(FullHttpResponse response) { else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); return finalResponse; } - - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 0c1260becf2..578526933ba 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ public interface InboundMessageType {} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 0dd17e9d4a9..2d5df10f8c1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType {} - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 67e2cb7165d..a4474b6b8b5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static com.google.common.truth.Truth.assertThat; @@ -20,7 +34,7 @@ import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { private LocalAddress localAddress; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index ab9997b6c68..06b19ea3607 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -20,10 +34,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - * It will either redirect the client to the correct location if given the + *

It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location + * an unexpected host location

*/ public class WebWhoisServer extends TestServer { From 37e32f95acc5c819ff1f13b8ff1a0c01dd2fba79 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 106/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 --- .../monitoring/blackbox/NewChannelAction.java | 144 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProberModule.java | 80 ++--- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingSequence.java | 130 ++++----- .../monitoring/blackbox/ProbingStep.java | 147 +++++----- .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/Protocol.java | 19 +- .../monitoring/blackbox/TokenModule.java | 35 --- .../monitoring/blackbox/Tokens/Token.java | 47 --- .../blackbox/Tokens/WebWhoisToken.java | 54 ---- .../monitoring/blackbox/WebWhoisModule.java | 169 ++++++----- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/ActionHandler.java | 105 +++++-- .../blackbox/handlers/MessageHandler.java | 24 -- .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../handlers/WebWhoisMessageHandler.java | 17 +- .../blackbox/messages/HttpRequestMessage.java | 46 ++- .../messages/HttpResponseMessage.java | 14 +- .../messages/OutboundMessageType.java | 11 +- .../monitoring/blackbox/tokens/Token.java | 43 +-- .../blackbox/tokens/WebWhoisToken.java | 62 ++-- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 32 files changed, 715 insertions(+), 973 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 73bd9127852..0daaf16ded4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,99 +14,59 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; import javax.inject.Singleton; +import org.joda.time.Duration; /** - * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} - * - *

Provides

+ * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores + * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. */ @Module public class ProberModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; + /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + private static final Duration DEFAULT_DURATION = new Duration(4000L); + + /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides - @HttpWhoisProtocol - ProbingSequence provideHttpWhoisSequence( - @HttpWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpsWhoisProtocol - ProbingSequence provideHttpsWhoisSequence( - @HttpsWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return httpWhoIsPort; - } - - @Provides - @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return httpsWhoIsPort; + @Singleton + Duration provideDuration() { + return DEFAULT_DURATION; } + /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - ImmutableMap providePortToProtocolMap( - Set protocolSet) { - return Maps.uniqueIndex(protocolSet, Protocol::port); + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - - + /** Root level {@link Component} that provides each {@link ProbingSequence}. */ @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, - TokenModule.class }) public interface ProberComponent { - @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); - - @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); - - ImmutableMap providePortToProtocolMap(); - - @WebWhoisProtocol Token provideWebWhoisToken(); + //Standard WebWhois sequence + @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2eb90a1d6c3..2dbf48256f9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,108 +14,100 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} - * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ - private EventLoopGroup eventGroup; + /**Each {@link ProbingSequence} requires a start token to begin running. */ + private Token startToken; - /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ - private Bootstrap bootstrap; - - public Bootstrap getBootstrap() { - return bootstrap; - } - - public void start(Token token) { - // calls the first step with input token; - firstStep.accept(token); + public void start() { + // calls the first step with startToken; + firstStep.accept(startToken); } /** - * {@link Builder} which takes in {@link ProbingStep}s - * - * @param Same specified {@code C} for overall {@link ProbingSequence} + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. */ - public static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstSequenceStep; - private EventLoopGroup eventLoopGroup; - private Class classType; - - Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public static class Builder { + + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstRepeatedStep; + private Bootstrap bootstrap; + private Token startToken; + + /** + * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. + * + *

Must be called before adding {@link ProbingStep.Builder}s.

+ */ + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } + + /** Adds start token that activate {@link ProbingSequence}. */ + public Builder addToken(Token token) { + startToken = token; return this; } - Builder addStep(ProbingStep step) { - if (currentStep == null) { + /** + * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * built, and pointed to by the previous {@link ProbingStep} added. + */ + public Builder addStep(ProbingStep.Builder stepBuilder) { + assert (bootstrap != null); + ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + + if (currentStep == null) firstStep = step; - } else { + else currentStep.nextStep(step); - } + currentStep = step; return this; } - /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ - Builder makeFirstRepeated() { - firstSequenceStep = currentStep; - return this; - } - /** Set the class to be the same as {@code C} */ - public Builder setClass(Class classType) { - this.classType = classType; + /** We take special note of the first repeated step. */ + public Builder markFirstRepeated() { + firstRepeatedStep = currentStep; return this; } - public ProbingSequence build() { - currentStep.nextStep(firstSequenceStep); + /** + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and + * calls private constructor to create {@link ProbingSequence}. + */ + public ProbingSequence build() { + if (firstRepeatedStep == null) + firstRepeatedStep = firstStep; + + currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); - return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + return new ProbingSequence(this.firstStep, this.startToken); } - } - /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ - private void setParents() { - ProbingStep currentStep = firstStep.parent(this).nextStep(); - - while (currentStep != firstStep) { - currentStep = currentStep.parent(this).nextStep(); - } - } - private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, - Class classType) { + private ProbingSequence(ProbingStep firstStep, Token startToken) { this.firstStep = firstStep; - this.eventGroup = eventLoopGroup; - this.bootstrap = new Bootstrap() - .group(eventGroup) - .channel(classType); - setParents(); - } - - @Override - public String toString() { - return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); - + this.startToken = startToken; } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 80b04a3d0c9..d54acef325a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,152 +14,145 @@ package google.registry.monitoring.blackbox; +import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.local.LocalAddress; - import java.util.function.Consumer; import org.joda.time.Duration; /** - * Represents generator of actions performed at each step in {@link ProbingSequence} - * - * @param See {@code C} in {@link ProbingSequence} + * {@link AutoValue} class that represents generator of actions performed at each step + * in {@link ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies - * these components on each loop iteration with the consumed {@link Token} and from that, - * generates new {@link ProbingAction} to perform<./p> + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. + * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, + * generates a new {@link ProbingAction} to call.

* - *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -public abstract class ProbingStep implements Consumer { +@AutoValue +public abstract class ProbingStep implements Consumer { - public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); - protected static final Duration DEFAULT_DURATION = new Duration(2000L); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - protected LocalAddress address = DEFAULT_ADDRESS; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ private boolean isLastStep = false; - private ProbingStep nextStep; - private ProbingSequence parent; + private ProbingStep nextStep; - protected Duration duration; + abstract Duration duration(); + abstract Protocol protocol(); + abstract OutboundMessageType messageTemplate(); + abstract Bootstrap bootstrap(); - protected final Protocol protocol; - protected final OutboundMessageType message; - protected ProbingStep(Protocol protocol, OutboundMessageType message) { - this.protocol = protocol; - this.message = message; - } + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder setDuration(Duration value); - private OutboundMessageType message() { - return message; - } + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); - Protocol protocol() { - return protocol; + public abstract ProbingStep build(); } + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - ProbingStep parent(ProbingSequence parent) { - this.parent = parent; - return this; - } - - /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ private ProbingAction generateAction(Token token) throws InternalException { - ProbingAction generatedAction; - - OutboundMessageType message = token.modifyMessage(message()); - - //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction - if (protocol().persistentConnection() && token.channel() != null) { - generatedAction = ExistingChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .channel(token.channel()) - .build(); - } else { - generatedAction = NewChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .bootstrap(parent.getBootstrap()) - .address(address) - .build(); - - } - return generatedAction; + OutboundMessageType message = token.modifyMessage(messageTemplate()); + ProbingAction.Builder probingActionBuilder = ProbingAction.builder() + .setDelay(duration()) + .setProtocol(protocol()) + .setOutboundMessage(message) + .setHost(token.getHost()) + .setBootstrap(bootstrap()); + + if (token.channel() != null) + probingActionBuilder.setChannel(token.channel()); + + return probingActionBuilder.build(); } - /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } @Override public void accept(Token token) { - ProbingAction nextAction; + ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - nextAction = generateAction(token); + currentAction = generateAction(token); } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - //If the next step maintains the connection, pass on the channel from this - if (protocol().persistentConnection()) { - token.channel(nextAction.channel()); - } + //call the created action - ChannelFuture future = nextAction.call(); + ChannelFuture future; + + try { + future = currentAction.call(); + + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Performed"); + nextStep.accept(generateNextToken(token)); + return; + } + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - nextStep.accept(generateNextToken(token)); + //If the next step maintains the connection, pass on the channel from this } else { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + token.setChannel(currentAction.channel()); + + nextStep.accept(generateNextToken(token)); + + }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n" + - "and parent sequence: %s", + "OutboundMessage: %s\n", protocol(), - message(), - parent); + messageTemplate().getClass().getName()); } + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 0fc3a3e09c3..ef52cb9c4bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -17,14 +17,18 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import io.netty.channel.ChannelHandler; +import io.netty.util.AttributeKey; import javax.inject.Provider; /** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. */ @AutoValue public abstract class Protocol { + /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + abstract String name(); public abstract int port(); @@ -35,22 +39,21 @@ public abstract class Protocol { /** Boolean that notes if connection associated with Protocol is persistent.*/ abstract boolean persistentConnection(); - public abstract Builder toBuilder(); - public static Builder builder() { return new AutoValue_Protocol.Builder(); } + /** Builder for {@link Protocol}. */ @AutoValue.Builder - public static abstract class Builder { + public abstract static class Builder { - public abstract Builder name(String value); + public abstract Builder setName(String value); - public abstract Builder port(int num); + public abstract Builder setPort(int num); - public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder setHandlerProviders(ImmutableList> providers); - public abstract Builder persistentConnection(boolean value); + public abstract Builder setPersistentConnection(boolean value); public abstract Protocol build(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 7200a1877e2..dcc9635beaa 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,62 +17,86 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; -import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandler; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - final static String DOMAIN_SUFFIX = "whois.nic."; + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + private static final String DOMAIN_PREFIX = "whois.nic."; + + /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + private static final int maximumMessageLengthBytes = 512 * 1024; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - - - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - - + /** {@link Provides} standard WebWhois sequence. */ @Provides - @HttpWhoisProtocol - static ProbingStep provideHttpWhoisProbingSequence( - @HttpWhoisProtocol Protocol httpWhoisProtocol) { - return new ProbingStepWeb<>(httpWhoisProtocol); + @WebWhoisProtocol + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, + WebWhoisToken webWhoisToken, + @WebWhoisProtocol Bootstrap bootstrap) { + + return new ProbingSequence.Builder() + .addToken(webWhoisToken) + .setBootstrap(bootstrap) + .addStep(probingStepBuilder) + .build(); } + + /** {@link Provides} only step used in WebWhois sequence. */ @Provides - @HttpsWhoisProtocol - static ProbingStep provideHttpsWhoisProbingStep( - @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { - return new ProbingStepWeb<>(httpsWhoisProtocol); + @WebWhoisProtocol + static ProbingStep.Builder provideWebWhoisStepBuilder( + @HttpWhoisProtocol Protocol httpWhoisProtocol, + HttpRequestMessage messageTemplate, + Duration duration) { + + return ProbingStep.builder() + .setProtocol(httpWhoisProtocol) + .setMessageTemplate(messageTemplate) + .setDuration(duration); } - + /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides @HttpWhoisProtocol @@ -80,28 +104,14 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpProtocolForSet( - @HttpWhoisProtocol int httpWhoisPort, - @HttpWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTP_PROTOCOL_NAME) + .setPort(httpWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } - + /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ @Singleton @Provides @HttpsWhoisProtocol @@ -109,40 +119,28 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpsProtocolForSet( - @HttpsWhoisProtocol int httpsWhoisPort, - @HttpsWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTPS_PROTOCOL_NAME) + .setPort(httpsWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } + /** {@link Provides} the prefix where we probe: "prefix.tld". */ @Provides - @WebWhoisProtocol - String provideHttpWhoisHost() { - return "app"; + @Named("Web-WHOIS-Prefix") + String provideWhoisPrefix() { + return DOMAIN_PREFIX; } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -151,13 +149,14 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -167,33 +166,57 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } + @Provides + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); + } + + @Provides + static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { + return new HttpObjectAggregator(maxContentLength); + } + + /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + @Provides + @HttpsWhoisProtocol + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); + } + /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + @Singleton @Provides @WebWhoisProtocol - static MessageHandler provideMessageHandler() { - return new WebWhoisMessageHandler(); + static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + return new Bootstrap() + .group(eventLoopGroup) + .channel(NioSocketChannel.class); } @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); + @WebWhoisProtocol + int provideMaximumMessageLengthBytes() { + return maximumMessageLengthBytes; } + /** {@link Provides} the list of top level domains to be probed */ + @Singleton @Provides - static HttpObjectAggregator provideHttpObjectAggregator() { - return new HttpObjectAggregator(1048576); + @WebWhoisProtocol + ImmutableList provideTopLevelDomains() { + return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); } @Provides - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index 776a231d6dd..be3d725c833 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,10 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when the action - * performed failed due to an issue in the connection with the server. + * Base exception class for all instances when the status of the action performed is ERROR. */ -public class ConnectionException extends UndeterminedStateException { +public class ConnectionException extends Exception { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index c3622e1b810..2e155b40afd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,10 +14,11 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.ChannelFuture; @@ -26,17 +27,18 @@ import io.netty.channel.SimpleChannelInboundHandler; /** - * Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, - * as it should only be passed in messages that implement the {@link InboundMessageType} interface. + *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link - * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. - * Second, it stores the {@link OutboundMessageType} passed down the pipeline, so that subclasses - * can use that information for their own processes. Lastly, with any exception thrown, the - * connection is closed, and the ProbingAction governing this channel is informed of the error. - * Subclasses specify further work to be done for specific kinds of channel pipelines. + *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed + * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} + * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * + *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -48,33 +50,41 @@ public enum ResponseType {SUCCESS, FAILURE, ERROR} /** Status of response for current {@link ActionHandler} instance */ private static ResponseType status; + /** {@link ChannelPromise} that informs {@link google.registry.monitoring.blackbox.ProbingAction} if response has been received. */ protected ChannelPromise finished; - /** - * Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized - * {@link ChannelPromise} - */ + /** Returns initialized {@link ChannelPromise} to {@link google.registry.monitoring.blackbox.ProbingAction}.*/ public ChannelFuture getFuture() { return finished; } - /** Initializes new {@link ChannelPromise} */ + /** Initializes the same {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { // Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } + /** Initializes the same {@link ChannelPromise} in case current channel is reused (usually for EPP).*/ + public void resetFuture() { + finished = finished.channel().newPromise(); + } + + /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { - //simply marks finished as success + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { + status = ResponseType.SUCCESS; - finished.setSuccess(); + + if (!finished.isSuccess()) { + finished.setSuccess(); + } } /** - * Logs the channel and pipeline that caused error, closes channel, then informs {@link - * ProbingAction} listeners of error + * Logs the channel and pipeline that caused error, closes channel, then informs + * {@link google.registry.monitoring.blackbox.ProbingAction} listeners of error. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { @@ -83,27 +93,62 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", ctx.channel().toString(), ctx.channel().pipeline().toString())); - - if (ResponseException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + if (cause instanceof ResponseException) { + //On ResponseException, we know the response is a failure. As a result, + //we set the status to FAILURE, then inform the MetricsHandler of this status = ResponseType.FAILURE; + + //Since it wasn't a success, we still want to log to see what caused the FAILURE logger.atInfo().log(cause.getMessage()); + + //As always, inform the ProbingStep that we successfully completed this action finished.setSuccess(); - } else if (ServerSideException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + + } else if (cause instanceof ConnectionException) { + //On ConnectionException, we know the response type is an error. As a result, + //we set the status to ERROR, then inform the MetricsHandler of this status = ResponseType.ERROR; + + //Since it wasn't a success, we still log what caused the ERROR logger.atInfo().log(cause.getMessage()); finished.setSuccess(); - } else if (InternalException.class.isInstance(cause)){ + + //As this was an ERROR in the connection, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + } else if (cause instanceof InternalException){ + //For an internal error, metrics should not be collected, so we log what caused this, and + //inform the ProbingStep the Prober had an internal error on this action logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); + + + //As this was an internal error, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } else { - finished.setFailure(cause); + //In the case of any other kind of error, we assume it is some type of connection ERROR, + //so we treat it as such: + + status = ResponseType.ERROR; + + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - //due to failure, close channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + + } + + /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ + @VisibleForTesting + ResponseType getStatus() { + return status; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index ac844ac99df..919006592ea 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -89,8 +90,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); - Protocol protocol = action.protocol(); + Protocol protocol = channel.attr(PROTOCOL_KEY).get(); + String host = channel.attr(REMOTE_ADDRESS_KEY).get(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -103,7 +104,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), action.host(), protocol.port()); + .newHandler(channel.alloc(), host, protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 0acf223eb9e..58c395ad86e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -17,37 +17,36 @@ import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; /** - * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection + * in case of reuse for redirection. */ -public class WebWhoisMessageHandler extends MessageHandler { - - private HttpRequestMessage request; +public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method*/ + /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - request = (HttpRequestMessage) msg; + HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; - InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); + HttpResponseMessage response = new HttpResponseMessage(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b06938d80a1..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,19 +19,30 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); @@ -39,18 +50,29 @@ public HttpRequestMessage setUri(String path) { } /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; - ByteBuf buf = request.content(); + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; - request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + } else { + throw new IllegalArgumentException(); + } + } - return finalRequest; + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 283b14440ac..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -34,17 +34,9 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 2d5df10f8c1..be6c872cc3e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,16 @@ package google.registry.monitoring.blackbox.messages; +import google.registry.monitoring.blackbox.exceptions.InternalException; + /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType {} +public interface OutboundMessageType { + + /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + public OutboundMessageType modifyMessage(String... args) throws InternalException; + + /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + public String name(); +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index b10c45dae8a..dd1882b5686 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,58 +14,41 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.ProbingSequence; -import google.registry.monitoring.blackbox.ProbingStep; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} in a single loop of a - * {@link ProbingSequence}. + * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} + * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes on channel that remains unchanged within a - * loop of the sequence.

+ * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop * in the sequence.

*/ public abstract class Token { - /** - * {@link Channel} that always starts out as null. Once a persistent connection is made (such as - * EPP), that channel is stored in the token and passed on to later steps in the sequence until a - * new loop begins. - */ + /** {@link Channel} that always starts out as null. */ protected Channel channel; - /** - * Obtains next {@link Token} for next loop in sequence. - */ + /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); - /** - * String corresponding to host that is relevant for loop in sequence. - */ - public abstract String host(); + /** String corresponding to host that is relevant for loop in sequence. */ + public abstract String getHost(); - /** - * Modifies the {@link OutboundMessageType} in the manner necessary for each loop - */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) - throws UndeterminedStateException; + /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; - /** - * Set method for {@code channel} - */ + /** Set method for {@code channel} */ public void setChannel(Channel channel) { this.channel = channel; } - /** - * Get method for {@code channel}. - */ + /** Get method for {@code channel}. */ public Channel channel() { return this.channel; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 3ff852f3556..2847e5ce0eb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,67 +16,59 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; +import java.util.List; import javax.inject.Inject; +import javax.inject.Named; /** * {@link Token} subtype designed for WebWhois sequence. * *

Between loops of a WebWhois sequence the only thing changing is the tld we - * are probing. As a result, we maintain the list of {@code topLevelDomains} and on each call to - * next, have our index looking at the next {@code topLevelDomain}.

+ * are probing. As a result, we maintain the list of {@code topLevelDomains} and + * on each call to next, have our index looking at the next {@code topLevelDomain}.

*/ public class WebWhoisToken extends Token { - /** - * For each top level domain (tld), we probe "prefix.tld". - */ - private static final String PREFIX = "whois.nic."; + /** For each top level domain (tld), we probe "prefix.tld". */ + private final String prefix; - /** - * {@link ImmutableList} of all top level domains to be probed. - */ - private final Iterator topLevelDomainsIterator; + /** {@link ImmutableList} of all top level domains to be probed. */ + private final ImmutableList topLevelDomains; - /** - * Current index of {@code topLevelDomains} that represents tld we are probing. - */ - private String currentDomain; + /** Current index of {@code topLevelDomains} that represents tld we are probing. */ + private int domainsIndex; @Inject - public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken( + @Named("Web-WHOIS-Prefix") String prefix, + @WebWhoisProtocol ImmutableList topLevelDomains) { - topLevelDomainsIterator = topLevelDomains.iterator(); - currentDomain = topLevelDomainsIterator.next(); + domainsIndex = 0; + this.prefix = prefix; + this.topLevelDomains = topLevelDomains; } - /** - * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. - */ + /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + domainsIndex += 1; + domainsIndex %= topLevelDomains.size(); return this; } - /** - * Modifies message to reflect the new host coming from the new top level domain. - */ + /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) - throws UndeterminedStateException { - return original.modifyMessage(host()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { + return original.modifyMessage(getHost()); } - /** - * Returns host as the concatenation of fixed {@code prefix} and current value of {@code - * topLevelDomains}. - */ + /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String host() { - return PREFIX + currentDomain; + public String getHost() { + return prefix + topLevelDomains.get(domainsIndex); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Mon, 29 Jul 2019 12:04:58 -0400 Subject: [PATCH 107/337] Minor Style Fixes --- .../monitoring/blackbox/ProbingAction.java | 85 ++++++++++--------- .../monitoring/blackbox/ProbingStep.java | 8 +- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..3f6a962b12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -89,11 +90,47 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** The {@link SocketAddress} instance that specifies remote address of connection */ + @Nullable public abstract SocketAddress address(); /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ public abstract Optional bootstrap(); + + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> actionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** * The method that performs the work of the actual action. * @@ -130,41 +167,13 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } @@ -224,7 +233,7 @@ public abstract static class Builder { abstract Channel channel(); - abstract Optional address(); + abstract SocketAddress address(); abstract Optional bootstrap(); @@ -233,7 +242,7 @@ public abstract static class Builder { abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) + if (address() == null) //If no address has been supplied, we set it based on the host and port setAddress(new InetSocketAddress(host(), protocol().port())); @@ -259,7 +268,7 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap().get().connect(address()); setChannel(connectionFuture.channel()); setConnectionFuture(connectionFuture); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index d54acef325a..47c89c72c11 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -21,7 +21,9 @@ import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import java.net.SocketAddress; import java.util.function.Consumer; +import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -48,6 +50,7 @@ public abstract class ProbingStep implements Consumer { abstract Protocol protocol(); abstract OutboundMessageType messageTemplate(); abstract Bootstrap bootstrap(); + @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -60,6 +63,8 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); + public abstract Builder setAddress(SocketAddress address); + public abstract ProbingStep build(); } @@ -87,7 +92,8 @@ private ProbingAction generateAction(Token token) throws InternalException { .setProtocol(protocol()) .setOutboundMessage(message) .setHost(token.getHost()) - .setBootstrap(bootstrap()); + .setBootstrap(bootstrap()) + .setAddress(address()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); From 62351d24313c03919d2c7c2bd89f1ed83f3f0400 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:05:59 -0400 Subject: [PATCH 108/337] Updated build.gradle file --- prober/build.gradle | 3 - .../blackbox/ProbingSequenceStepTest.java | 219 ----------------- .../blackbox/ProbingSequenceTest.java | 96 -------- .../monitoring/blackbox/ProbingStepTest.java | 223 +++++++++--------- 4 files changed, 110 insertions(+), 431 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java diff --git a/prober/build.gradle b/prober/build.gradle index 993da44655d..181188c5cee 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,7 +16,6 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - dependencies { def deps = rootProject.dependencyMap @@ -45,7 +44,6 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -55,4 +53,3 @@ dependencies { testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java deleted file mode 100644 index 7a713017072..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.TestUtils.TestStep; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.handlers.ConversionHandler; -import google.registry.monitoring.blackbox.handlers.NettyRule; -import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; -import org.junit.Rule; -import org.junit.Test; - -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { - - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ - private ProbingSequence testSequence; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); - dummyStep = new DummyStep(testProtocol, eventLoopGroup); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(false) - .build(); - } - - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(true) - .build(); - } - - /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ - private void setupSequence() { - testSequence = new ProbingSequence.Builder() - .eventLoopGroup(eventLoopGroup) - .setClass(LocalChannel.class) - .addStep(firstStep) - .makeFirstRepeated() - .addStep(dummyStep) - .build(); - } - - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.nextStep()).isNull(); - - //we expect that this exception be thrown - assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); - - } - - @Test - public void testWithSequence_NewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupSequence(); - setupNewChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupSequence(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 5c4452df7b3..2b0559514a2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,101 +1,5 @@ -// Copyright 2019 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.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doCallRealMethod; - -import google.registry.monitoring.blackbox.tokens.Token; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) public class ProbingSequenceTest { - - private ProbingStep setupMock() { - ProbingStep mock = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(mock).nextStep(); - return mock; - } - - private static class Wrapper { - - T data; - - public Wrapper(T data) { - this.data = data; - } - } - - @Test - public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(firstStep) - .addStep(secondStep) - .addStep(thirdStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(thirdStep); - assertThat(thirdStep.nextStep()).isEqualTo(firstStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - - @Test - public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(thirdStep) - .addStep(secondStep) - .markFirstRepeated() - .addStep(firstStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(firstStep); - assertThat(thirdStep.nextStep()).isEqualTo(secondStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 307d19221dd..090753014e4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,203 +11,200 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.TestUtils.dummyStep; +import static google.registry.monitoring.blackbox.TestUtils.testStep; +import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; -import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; -import org.mockito.Mockito; - -/** - * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific - * implementations - */ -public class ProbingStepTest { - - /** - * Basic Constants necessary for tests - */ - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final int PROTOCOL_PORT = 0; - private static final String TEST_MESSAGE = "TEST_MESSAGE"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - private static final LocalAddress ADDRESS = new LocalAddress(ADDRESS_NAME); + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - /** - * Used for testing how well probing step can create connection to blackbox server - */ + /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** - * The two main handlers we need in any test pipeline used that connects to {@link NettyRule's - * server} - **/ + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** - * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} - * is called, it just marks the supplied future as succeeded, returning the requisite token. - */ - private ProbingStep dummyStep() { - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(dummyStep).nextStep(); - return dummyStep; + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); } + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } - @Test - public void testNewChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } - // Sets up Protocol for when we create a new channel. - Protocol testProtocol = Protocol.builder() + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); + dummyStep = dummyStep(eventLoopGroup); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); + } - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) .build(); + } - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); + //there should be no next step + assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); - //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(ADDRESS); + } + + @Test + public void testNewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //checks that we have appropriately sent the write message to server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - verify(dummyStep, times(1)).accept(any(Token.class)); + assertThat(future.get()).isEqualTo(testToken); + } - @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - - // Sets up Protocol for when a channel already exists. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) - .build(); - - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) - .build(); - - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); - - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - - //Assures that the channel has a succeeded connectionFuture. - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, ""); + //setup + setupExistingProtocol(); + setupSteps(); + setupChannel(); + setupExistingChannelToken(); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message through the EmbeddedChannel - // pipeline + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); - Object msg = channel.readOutbound(); - - while (msg == null) { - msg = channel.readOutbound(); - } //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf) channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked - // as a success - verify(dummyStep, times(1)).accept(any(Token.class)); + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); } } From 54493e44146099c5720f3691c4682d419ad07ac1 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 109/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From 41d6c5d325d89c0f97367c76942012efb1583b57 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:54:13 -0400 Subject: [PATCH 110/337] Updated WebWhois tests. --- .../blackbox/ProbingActionTest.java | 56 +++--- .../blackbox/ProbingSequenceTest.java | 183 ++++++++++++++++++ .../monitoring/blackbox/ProbingStepTest.java | 3 +- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 93 +++++++-- .../monitoring/blackbox/TokenTest.java | 13 +- .../blackbox/handlers/ConversionHandler.java | 2 +- .../blackbox/handlers/NettyRule.java | 12 +- .../handlers/SslClientInitializerTest.java | 46 ++--- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 158 ++++++++------- 11 files changed, 421 insertions(+), 157 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index cbcf2fc82b0..162044c2036 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -83,31 +84,31 @@ public class ProbingActionTest { /** Sets up a {@link Protocol} corresponding to when a new connection is created */ private void setupNewChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(false) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) .build(); } /** Sets up a {@link Protocol} corresponding to when a new connection exists */ private void setupExistingChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(true) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(true) .build(); } - /** Sets up a {@link NewChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ private void setupNewChannelAction() { - newChannelAction = NewChannelAction.builder() - .bootstrap(bootstrap) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") - .address(address) + newChannelAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") + .setAddress(address) .build(); } @@ -115,25 +116,25 @@ private void setupChannel() { channel = new EmbeddedChannel(); } - /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ExistingChannelAction.builder() - .channel(channel) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") + existingChannelAction = ProbingAction.builder() + .setChannel(channel) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") .build(); } @Test - public void testBehavior_existingChannel() { + public void testBehavior_existingChannel() throws InternalException { //setup setupChannel(); setupExistingChannelProtocol(); - setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); + setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -147,6 +148,7 @@ public void testBehavior_existingChannel() { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -156,9 +158,9 @@ public void testBehavior_existingChannel() { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - setupNewChannelAction(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + setupNewChannelAction(); ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2b0559514a2..681a5346d55 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,5 +1,188 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; + +import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; +import java.net.SocketAddress; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) public class ProbingSequenceTest { + private final static String TEST_HOST = "TEST_HOST"; + + + private Bootstrap dummyBootstrap = new Bootstrap(); + private Token testToken = new ProbingSequenceTestToken(); + + /** + * Custom {@link ProbingStep} subclass that acts as a mock + * step, so we can test how well {@link ProbingSequence} builds + * a linked list of {@link ProbingStep}s from their {@link Builder}s. + */ + private static class TestStep extends ProbingStep { + private Bootstrap bootstrap; + private String marker; + + /** We implement all abstract methods to simply return null, as we have no use for them here. */ + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + SocketAddress address() { + return null; + } + + /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + /** + * Builder for {@link TestStep}, that extends {@link ProbingStep.Builder} so that these can be + * input into the {@link ProbingSequence.Builder}. + */ + public static class Builder extends ProbingStep.Builder { + /** We test to see if we accurately add the right bootstrap to all {@link ProbingStep}s/ */ + private Bootstrap bootstrap; + + /** We also mark each step in order to ensure that when running, they are arranged in the right order. */ + private String marker; + + @Override + public ProbingStep.Builder setDuration(Duration value) { + return this; + } + + @Override + public ProbingStep.Builder setProtocol(Protocol value) { + return this; + } + + @Override + public ProbingStep.Builder setMessageTemplate(OutboundMessageType value) { + return null; + } + + @Override + public ProbingStep.Builder setAddress(SocketAddress address) { + return null; + } + + @Override + public ProbingStep.Builder setBootstrap(Bootstrap value) { + bootstrap = value; + return this; + } + + public ProbingStep.Builder addMarker(String value) { + marker = value; + return this; + } + + @Override + public ProbingStep build() { + return new TestStep(bootstrap, marker); + } + } + private TestStep(Bootstrap bootstrap, String marker) { + this.bootstrap = bootstrap; + this.marker = marker; + } + + /** + * On a call to accept, we modify the token to reflect what the current step is, so we can get + * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated + * in order. + */ + @Override + public void accept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + if (!isLastStep) { + nextStep().accept(token); + } else { + ((TestStep)nextStep()).specialAccept(token); + } + } + + /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ + public void specialAccept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + return; + } + } + + @Test + public void testSequenceBasicConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("firstsecondthirdfirst"); + } + + @Test + public void testSequenceAdvancedConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(thirdStepBuilder) + .addStep(secondStepBuilder) + .markFirstRepeated() + .addStep(firstStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("thirdsecondfirstsecond"); + } + @Test + public void testSequenceConstruction_Failure() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + assertThrows(AssertionError.class, () -> { + ProbingSequence sequence = new ProbingSequence.Builder() + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .setBootstrap(dummyBootstrap) + .build(); + }); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 090753014e4..ee38e7cdf74 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -21,7 +21,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; @@ -47,7 +46,7 @@ import org.junit.Test; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { +public class ProbingStepTest { /** Basic Constants necessary for tests */ private final String ADDRESS_NAME = "TEST_ADDRESS"; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 06b19ea3607..337d755e971 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -93,11 +93,11 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 8d1722c9625..161304c1f04 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,9 +17,11 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -37,6 +39,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; +import java.net.Socket; +import java.net.SocketAddress; +import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -141,26 +146,67 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } + + @Override + public OutboundMessageType modifyMessage(String... args) throws InternalException { + message = args[0]; + return this; + } + + @Override + public String name() { + return "Test Message of: " + this.toString(); + } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static class TestStep extends ProbingStep { + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .setAddress(address) + .build(); - public TestStep(Protocol protocol, String testMessage, LocalAddress address) { - super(protocol, new DuplexMessageTest(testMessage)); - this.address = address; - this.duration = Duration.ZERO; - } + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { - super(protocol, new DuplexMessageTest()); - future = new DefaultPromise(eventLoopGroup.next()) {}; - duration = Duration.ZERO; + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; + } + + @Nullable + @Override + SocketAddress address() { + return null; } @Override @@ -170,11 +216,16 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } + + @Override + public String toString() { + return "Dummy Step"; + } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - private String host; + protected String host; protected TestToken(String host) { this.host = host; @@ -221,6 +272,22 @@ public Channel channel() { } } + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..67963805733 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,10 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; @@ -34,20 +35,20 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..a8506a996a9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -37,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b6b5e8fbe0c..b38c1911940 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; @@ -89,7 +90,8 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - ProbingAction probingAction, + Protocol protocol, + String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -109,7 +111,9 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROBING_ACTION_KEY, probingAction); + .attr(PROTOCOL_KEY, protocol) + .attr(REMOTE_ADDRESS_KEY, host); + channel = b.connect(localAddress).syncUninterruptibly().channel(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 469c62a8f75..83c8e132f07 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,17 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ExistingChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; @@ -45,7 +46,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; -import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,8 +67,6 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); - /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -93,15 +91,12 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .persistentConnection(false) - .build(); - - private ProbingAction probingAction; + private final static Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -113,23 +108,13 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } - private void setupProbingAction(Channel channel) { - probingAction = ExistingChannelAction.builder() - .delay(Duration.ZERO) - .host(SSL_HOST) - .channel(channel) - .outboundMessage(DEFAULT_MESSAGE) - .protocol(PROTOCOL) - .build(); - } - @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - setupProbingAction(channel); - channel.attr(PROBING_ACTION_KEY).set(probingAction); + channel.attr(PROTOCOL_KEY).set(PROTOCOL); + channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -160,8 +145,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -189,8 +173,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -219,8 +202,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 518bb9ba686..e170fad8b8c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox.handlers; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 71d8d66b6c0..00318ccd912 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,17 +15,17 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; @@ -37,9 +37,7 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; @@ -66,6 +64,14 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); + private static final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of()) + .setName("test_protocol") + .setPersistentConnection(false) + .setPort(HTTPS_PORT) + .build(); + private LocalAddress address; private EmbeddedChannel channel; @@ -76,30 +82,38 @@ public class WebWhoisActionHandlerTest { private void generateLocalAddress() { address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); } + /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { + private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of(actionHandlerProvider)) - .persistentConnection(false) + .setName(name) + .setPort(port) + .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) + .setPersistentConnection(persistentConnection) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); + private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { + actionHandler = new WebWhoisActionHandler( + bootstrap, + STANDARD_PROTOCOL, + STANDARD_PROTOCOL, + messageTemplate, + 80, + 443 + ); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); setupProbingActionBasic( protocol, outboundMessage, makeBootstrap(new NioEventLoopGroup(1))); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -109,24 +123,25 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { } /**Sets up probingAction for when testing redirection */ private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(TARGET_HOST) - .address(DEFAULT_ADDRESS) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(TARGET_HOST) + .setAddress(DEFAULT_ADDRESS) + .setChannel(channel) .build(); } private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(host) - .address(address) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(host) + .setAddress(address) .build(); } @@ -137,10 +152,13 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, true); generateLocalAddress(); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); @@ -150,7 +168,7 @@ public void testBasic_responseOk() throws Exception { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -166,9 +184,10 @@ public void testBasic_responseOk() throws Exception { @Test public void testBasic_responseFailure() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseBad", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseBad", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -179,8 +198,7 @@ public void testBasic_responseFailure() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage - .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -197,9 +215,10 @@ public void testBasic_responseFailure() { @Test public void testBasic_responseError() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseError", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseError", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -211,7 +230,7 @@ public void testBasic_responseError() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -222,26 +241,30 @@ public void testBasic_responseError() { assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_redirectCloseChannel() { //setup - HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", 0); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", 0, true); generateLocalAddress(); - setupChannel(initialProtocol, outboundMessage); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -257,12 +280,15 @@ public void testBasic_redirectCloseChannel() { @Test public void testBasic_redirectHost() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); generateLocalAddress(); setupChannel(initialProtocol, msg); - HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); //store future @@ -272,27 +298,24 @@ public void testBasic_redirectHost() { channel.writeInbound(originalResponse); - ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - //gets changed protocol - Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); - assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); } @Test - public void testAdvanced_responseOk() { + public void testAdvanced_responseOk() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); //stores future ChannelFuture future = probingAction.call(); @@ -302,15 +325,16 @@ public void testAdvanced_responseOk() { } @Test - public void testAdvanced_responseFailure() { + public void testAdvanced_responseFailure() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); //stores future ChannelFuture future = probingAction.call(); From 8e589cdca2c575cd004d991daa46e50297b750e4 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 111/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- prober/.gitignore | 1 + .../registry/monitoring/blackbox/Prober.java | 9 +- .../monitoring/blackbox/ProberModule.java | 15 ++- .../monitoring/blackbox/ProbingAction.java | 96 +++++++-------- .../monitoring/blackbox/ProbingSequence.java | 24 +--- .../monitoring/blackbox/ProbingStep.java | 55 ++++++--- .../monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 49 ++++---- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 30 ----- .../exceptions/ResponseException.java | 29 ----- .../UndeterminedStateException.java | 5 +- .../blackbox/handlers/ActionHandler.java | 102 ++++------------ .../handlers/WebWhoisActionHandler.java | 51 ++++---- .../blackbox/messages/HttpRequestMessage.java | 4 +- .../messages/HttpResponseMessage.java | 6 +- .../messages/OutboundMessageType.java | 7 +- .../monitoring/blackbox/tokens/Token.java | 20 +-- .../blackbox/tokens/WebWhoisToken.java | 32 +++-- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../blackbox/ProbingActionTest.java | 9 +- .../blackbox/ProbingSequenceTest.java | 114 +++--------------- .../monitoring/blackbox/ProbingStepTest.java | 4 +- .../monitoring/blackbox/TestUtils.java | 21 +--- .../monitoring/blackbox/TokenTest.java | 8 +- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 103 +++++----------- 31 files changed, 283 insertions(+), 528 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/.gitignore b/prober/.gitignore index 89f9ac04aac..77b1e2de2de 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1 +1,2 @@ out/ +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..307afd34d81 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +29,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 0daaf16ded4..1db97d1b581 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,14 +14,18 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.Set; import javax.inject.Singleton; import org.joda.time.Duration; @@ -33,7 +37,7 @@ public class ProberModule { /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = new Duration(4000L); + private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @@ -42,6 +46,12 @@ EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + @Provides + @Singleton + Class provideChannelClass() { + return NioSocketChannel.class; + } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides @Singleton @@ -51,6 +61,7 @@ Duration provideDuration() { /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides + @Singleton static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; @@ -66,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); + Set provideAllSequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 3f6a962b12d..67494dd5f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,25 +14,29 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -65,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -80,31 +87,18 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - @Nullable - public abstract SocketAddress address(); - - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { // Write appropriate outboundMessage to pipeline ChannelFuture channelFuture = actionHandler.getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> actionHandler.resetFuture(), - //inform ProbingStep of the status of our action future -> { if (future.isSuccess()) @@ -141,7 +135,7 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -154,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -180,19 +174,24 @@ public ChannelFuture performAction() throws InternalException { /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -210,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -221,40 +226,30 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract SocketAddress address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (address() == null) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + System.out.println("test"); + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -268,14 +263,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -293,7 +285,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2dbf48256f9..91c4165c068 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -49,32 +49,18 @@ public static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; private ProbingStep firstRepeatedStep; - private Bootstrap bootstrap; - private Token startToken; - /** - * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. - * - *

Must be called before adding {@link ProbingStep.Builder}s.

- */ - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } + private Token startToken; - /** Adds start token that activate {@link ProbingSequence}. */ - public Builder addToken(Token token) { - startToken = token; - return this; + public Builder(Token startToken) { + this.startToken = startToken; } /** - * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, * built, and pointed to by the previous {@link ProbingStep} added. */ - public Builder addStep(ProbingStep.Builder stepBuilder) { - assert (bootstrap != null); - ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + public Builder addStep(ProbingStep step) { if (currentStep == null) firstStep = step; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 47c89c72c11..ca980100067 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import java.net.SocketAddress; import java.util.function.Consumer; -import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -39,18 +37,23 @@ @AutoValue public abstract class ProbingStep implements Consumer { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ - private boolean isLastStep = false; + protected boolean isLastStep = false; private ProbingStep nextStep; + /** Time delay duration between actions. */ abstract Duration duration(); + + /** {@link Protocol} type for this step. */ abstract Protocol protocol(); + + /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ abstract OutboundMessageType messageTemplate(); + + /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ abstract Bootstrap bootstrap(); - @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -63,8 +66,6 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); - public abstract Builder setAddress(SocketAddress address); - public abstract ProbingStep build(); } @@ -85,18 +86,18 @@ ProbingStep nextStep() { } /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws InternalException { + private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) .setProtocol(protocol()) .setOutboundMessage(message) - .setHost(token.getHost()) - .setBootstrap(bootstrap()) - .setAddress(address()); + .setHost(token.host()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); + else + probingActionBuilder.setBootstrap(bootstrap()); return probingActionBuilder.build(); } @@ -107,44 +108,58 @@ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } + /** + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. + * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

+ */ @Override public void accept(Token token) { ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - //call the created action ChannelFuture future; - try { + //call the generated action future = currentAction.call(); - - } catch(InternalException e) { + } catch(UndeterminedStateException e) { + //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); + + //Move on to next step in ProbingSequence nextStep.accept(generateNextToken(token)); return; } - //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - //If the next step maintains the connection, pass on the channel from this + } else { + //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index ef52cb9c4bf..624f08fd4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -29,7 +29,7 @@ public abstract class Protocol { /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - abstract String name(); + public abstract String name(); public abstract int port(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dcc9635beaa..c5e41fea38b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,6 +18,7 @@ import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,6 +27,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; @@ -44,11 +46,10 @@ @Module public class WebWhoisModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - private static final String DOMAIN_PREFIX = "whois.nic."; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; + private static final String HTTP_PROTOCOL_NAME = "http"; + private static final String HTTPS_PROTOCOL_NAME = "https"; /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; @@ -68,16 +69,14 @@ public class WebWhoisModule { /** {@link Provides} standard WebWhois sequence. */ @Provides - @WebWhoisProtocol + @Singleton + @IntoSet ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, - WebWhoisToken webWhoisToken, - @WebWhoisProtocol Bootstrap bootstrap) { + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { - return new ProbingSequence.Builder() - .addToken(webWhoisToken) - .setBootstrap(bootstrap) - .addStep(probingStepBuilder) + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) .build(); } @@ -85,15 +84,18 @@ ProbingSequence provideWebWhoisSequence( /** {@link Provides} only step used in WebWhois sequence. */ @Provides @WebWhoisProtocol - static ProbingStep.Builder provideWebWhoisStepBuilder( + static ProbingStep provideWebWhoisStep( @HttpWhoisProtocol Protocol httpWhoisProtocol, + @WebWhoisProtocol Bootstrap bootstrap, HttpRequestMessage messageTemplate, Duration duration) { return ProbingStep.builder() .setProtocol(httpWhoisProtocol) + .setBootstrap(bootstrap) .setMessageTemplate(messageTemplate) - .setDuration(duration); + .setDuration(duration) + .build(); } /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @@ -126,13 +128,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** {@link Provides} the prefix where we probe: "prefix.tld". */ - @Provides - @Named("Web-WHOIS-Prefix") - String provideWhoisPrefix() { - return DOMAIN_PREFIX; - } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @@ -187,10 +182,12 @@ static SslClientInitializer provideSslClientInitializer(SslPro @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + static Bootstrap provideBootstrap( + EventLoopGroup eventLoopGroup, + Class channelClass){ return new Bootstrap() .group(eventLoopGroup) - .channel(NioSocketChannel.class); + .channel(channelClass); } @Provides @@ -210,13 +207,13 @@ ImmutableList provideTopLevelDomains() { @Provides @HttpWhoisProtocol int provideHttpWhoisPort() { - return httpWhoIsPort; + return HTTP_WHOIS_PORT; } @Provides @HttpsWhoisProtocol int provideHttpsWhoisPort() { - return httpsWhoIsPort; + return HTTPS_WHOIS_PORT; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index be3d725c833..adb833ec629 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,9 +15,10 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is ERROR. + * Subclass of {@link UndeterminedStateException} that represents all instances when + * the action performed failed due to an issue in the connection with the server. */ -public class ConnectionException extends Exception { +public class ConnectionException extends UndeterminedStateException { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java index d7127717d52..c155d695c7f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java @@ -15,8 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails before we can determine - * the state of the result, meaning the status is recorded as ERROR. + * Base exception class for all instances when the action performed fails + * before we can determine the state of the result, meaning the status + * is recorded as ERROR. */ public class UndeterminedStateException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 2e155b40afd..247424243cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,17 +14,15 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; /** *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline @@ -33,7 +31,7 @@ * messages that implement the {@link InboundMessageType} interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

@@ -44,111 +42,59 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); - - } else if (cause instanceof InternalException){ - //For an internal error, metrics should not be collected, so we log what caused this, and - //inform the ProbingStep the Prober had an internal error on this action - logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - - //As this was an internal error, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } else { - //In the case of any other kind of error, we assume it is some type of connection ERROR, - //so we treat it as such: - - status = ResponseType.ERROR; + //On UndeterminedStateException, we know the response type is an error. - logger.atInfo().log(cause.getMessage()); - finished.setSuccess(); + //Since it wasn't a success, we still log what caused the ERROR + logger.atWarning().log(cause.getMessage()); + finished.setFailure(cause); + //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } - - /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ - @VisibleForTesting - ResponseType getStatus() { - return status; - } -} - +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 69d5b7f1603..1ec4e314813 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -22,13 +22,12 @@ import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -62,27 +61,17 @@ public class WebWhoisActionHandler extends ActionHandler { /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ private final HttpRequestMessage requestMessage; - /** Default port for http. */ - private int httpPort; - - /** default port for https. */ - private int httpsPort; - @Inject public WebWhoisActionHandler( @WebWhoisProtocol Bootstrap bootstrap, @HttpWhoisProtocol Protocol httpWhoisProtocol, @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage, - @HttpWhoisProtocol int httpPort, - @HttpsWhoisProtocol int httpsPort) { + HttpRequestMessage requestMessage) { this.bootstrap = bootstrap; this.httpWhoisProtocol = httpWhoisProtocol; this.httpsWhoisProtocol = httpsWhoisProtocol; this.requestMessage = requestMessage; - this.httpPort = httpPort; - this.httpsPort = httpsPort; } @@ -93,7 +82,7 @@ public WebWhoisActionHandler( */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -112,7 +101,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -123,12 +112,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; - if (newPort == httpPort) { + if (url.getProtocol().equals(httpWhoisProtocol.name())) { newProtocol = httpWhoisProtocol; - } else if (newPort == httpsPort) { + } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -143,34 +132,38 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) .setHost(newHost) .build(); - //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); - //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..b4c01d06a8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,12 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..f1b2d6ac6a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -25,11 +25,7 @@ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { - super(version, status); - } - - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index be6c872cc3e..6e3da3f69d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,7 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline @@ -22,8 +22,9 @@ public interface OutboundMessageType { /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - public OutboundMessageType modifyMessage(String... args) throws InternalException; + OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - public String name(); + @Override + String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dd1882b5686..dab5851e8d8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,16 +14,18 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.ProbingSequence; +import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} - * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} + * in a single loop of a {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * in a {@link ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -31,17 +33,21 @@ */ public abstract class Token { - /** {@link Channel} that always starts out as null. */ + /** + * {@link Channel} that always starts out as null. Once a persistent connection + * is made (such as EPP), that channel is stored in the token and passed on to + * later steps in the sequence until a new loop begins. + */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String getHost(); + public abstract String host(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 2847e5ce0eb..bb06ee89db6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import javax.inject.Inject; import javax.inject.Named; @@ -33,42 +33,38 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final String prefix; + private final static String PREFIX = "whois.nic."; /** {@link ImmutableList} of all top level domains to be probed. */ - private final ImmutableList topLevelDomains; + private final Iterator topLevelDomainsIterator; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private int domainsIndex; + private String currentDomain; @Inject - public WebWhoisToken( - @Named("Web-WHOIS-Prefix") String prefix, - @WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { - domainsIndex = 0; - this.prefix = prefix; - this.topLevelDomains = topLevelDomains; + topLevelDomainsIterator = topLevelDomains.iterator(); + currentDomain = topLevelDomainsIterator.next(); } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - domainsIndex += 1; - domainsIndex %= topLevelDomains.size(); + currentDomain = topLevelDomainsIterator.next(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { - return original.modifyMessage(getHost()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + return original.modifyMessage(host()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String getHost() { - return prefix + topLevelDomains.get(domainsIndex); + public String host() { + return PREFIX + currentDomain; } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( { - ProbingSequence sequence = new ProbingSequence.Builder() - .addStep(firstStepBuilder) - .addStep(secondStepBuilder) - .addStep(thirdStepBuilder) - .addToken(testToken) - .setBootstrap(dummyBootstrap) - .build(); - }); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index ee38e7cdf74..7bba9d66782 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.TestUtils.dummyStep; import static google.registry.monitoring.blackbox.TestUtils.testStep; import static google.registry.testing.JUnitBackports.assertThrows; @@ -90,7 +91,7 @@ public class ProbingStepTest { /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ private void setupNewChannelToken() { - testToken = new NewChannelToken(""); + testToken = new NewChannelToken(ADDRESS_NAME); } /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ @@ -101,6 +102,7 @@ private void setupExistingChannelToken() { /** Sets up an embedded channel to contain the two handlers we created already */ private void setupChannel() { channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 161304c1f04..68bdd0bcef0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,7 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,8 +26,6 @@ import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpMessage; @@ -39,7 +37,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; -import java.net.Socket; import java.net.SocketAddress; import javax.annotation.Nullable; import javax.inject.Provider; @@ -148,15 +145,10 @@ public String toString() { } @Override - public OutboundMessageType modifyMessage(String... args) throws InternalException { + public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { message = args[0]; return this; } - - @Override - public String name() { - return "Test Message of: " + this.toString(); - } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ @@ -166,7 +158,6 @@ public static ProbingStep testStep(Protocol protocol, String testMessage, Bootst .setDuration(Duration.ZERO) .setMessageTemplate(new DuplexMessageTest(testMessage)) .setBootstrap(bootstrap) - .setAddress(address) .build(); } @@ -203,12 +194,6 @@ Bootstrap bootstrap() { return null; } - @Nullable - @Override - SocketAddress address() { - return null; - } - @Override public void accept(Token token) { future.setSuccess(token); @@ -241,7 +226,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String getHost() { + public String host() { return host; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index 67963805733..295bb809a13 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -17,12 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -37,7 +35,7 @@ public class TokenTest { private static String TEST_STARTER = "starter"; private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { @@ -49,7 +47,7 @@ public void testWebToken_MessageModificationSuccess() { try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index e170fad8b8c..3ecbdcc0d06 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -29,7 +29,7 @@ public class TestActionHandler extends ActionHandler { @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 00318ccd912..83d004d4555 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,17 +15,20 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; @@ -63,11 +66,9 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); private static final Protocol STANDARD_PROTOCOL = Protocol.builder() .setHandlerProviders(ImmutableList.of()) - .setName("test_protocol") + .setName("http") .setPersistentConnection(false) .setPort(HTTPS_PORT) .build(); @@ -79,8 +80,10 @@ public class WebWhoisActionHandlerTest { private ProbingAction probingAction; private Provider actionHandlerProvider; - private void generateLocalAddress() { - address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + private String generateLocalAddress(String addressString) { + String modifiedAddress = addressString + System.currentTimeMillis(); + address = new LocalAddress(modifiedAddress); + return modifiedAddress; } /** Creates default protocol with empty list of handlers and specified other inputs */ @@ -99,9 +102,7 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT bootstrap, STANDARD_PROTOCOL, STANDARD_PROTOCOL, - messageTemplate, - 80, - 443 + messageTemplate ); actionHandlerProvider = new TestProvider<>(actionHandler); } @@ -110,10 +111,8 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - setupProbingActionBasic( - protocol, - outboundMessage, - makeBootstrap(new NioEventLoopGroup(1))); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -122,26 +121,23 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } /**Sets up probingAction for when testing redirection */ - private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) .setHost(TARGET_HOST) - .setAddress(DEFAULT_ADDRESS) .setChannel(channel) .build(); } - private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) .setBootstrap(bootstrap) - .setHost(host) - .setAddress(address) + .setHost(addressString) .build(); } @@ -156,8 +152,6 @@ public void testBasic_responseOk() throws Exception { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseOk", 0, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); //stores future @@ -182,13 +176,12 @@ public void testBasic_responseOk() throws Exception { } @Test - public void testBasic_responseFailure() { + public void testBasic_responseFailure_badRequest() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseBad", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -210,16 +203,15 @@ public void testBasic_responseFailure() { assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testBasic_responseError() { + public void testBasic_responseFailure_badURL() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseError", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -239,9 +231,9 @@ public void testBasic_responseError() { //assesses that listener is triggered, and event is success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException); } @Test @@ -253,7 +245,6 @@ public void testBasic_redirectCloseChannel() { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("redirectHttp", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -278,44 +269,15 @@ public void testBasic_redirectCloseChannel() { } @Test - public void testBasic_redirectHost() { - //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); - HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); - - - //store future - ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); - - - channel.writeInbound(originalResponse); - - Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - } - - @Test - public void testAdvanced_responseOk() throws InternalException { + public void testAdvanced_responseOk() throws UndeterminedStateException { //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); @@ -325,22 +287,21 @@ public void testAdvanced_responseOk() throws InternalException { } @Test - public void testAdvanced_responseFailure() throws InternalException { + public void testAdvanced_responseFailure() throws UndeterminedStateException { //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); + String host = generateLocalAddress(TARGET_HOST); HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(bootstrap, msg); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + assertThrows(FailureException.class, future::syncUninterruptibly); } } From 4314613f69089e35001c04e3cc2126f63cbdc0db Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:48:33 -0400 Subject: [PATCH 112/337] SpotlessApply run to fix style issues --- prober/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index 77b1e2de2de..c86568e7672 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From 2f38a3f51a593fc8bdcc6f93eeb5944370e6ae85 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:28:40 -0400 Subject: [PATCH 113/337] Added license header and newline where appropriate. --- prober/build.gradle | 1 + .../monitoring/blackbox/ProbingAction.java | 1 - .../blackbox/handlers/ActionHandler.java | 2 +- .../monitoring/blackbox/ProbingSequenceTest.java | 14 ++++++++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 181188c5cee..478d33e1ef9 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -35,6 +35,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] + compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 67494dd5f78..a8740e21c20 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -240,7 +240,6 @@ public ProbingAction build() { InetAddress hostAddress = InetAddress.getByName(host()); address = new InetSocketAddress(hostAddress, protocol().port()); } catch (UnknownHostException e) { - System.out.println("test"); address = new LocalAddress(host()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 247424243cb..433604d6495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -97,4 +97,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } -} \ No newline at end of file +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2a8d5ebe233..8d9e45c6a66 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; From 22583940f15443fd323a18dc915314116997bd8c Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 114/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/ProbingStepTest.java | 1 - .../blackbox/TestServers/WebWhoisServer.java | 3 +- .../monitoring/blackbox/TestUtils.java | 35 +------------------ .../blackbox/handlers/ConversionHandler.java | 5 ++- .../blackbox/handlers/NettyRule.java | 4 ++- 5 files changed, 10 insertions(+), 38 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 7bba9d66782..73b104ae5dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -174,7 +174,6 @@ public void testNewChannel() throws Exception { //checks that when the future is successful, we pass down the requisite token assertThat(future.get()).isEqualTo(testToken); - } @Test diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 337d755e971..e7f125bb906 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; @@ -80,7 +81,7 @@ static class RedirectHandler extends ChannelDuplexHandler { /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 68bdd0bcef0..cc8e1512fe9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; @@ -28,17 +27,13 @@ import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpMethod;; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; import java.net.SocketAddress; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -272,33 +267,5 @@ public void addToHost(String suffix) { } } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index a8506a996a9..196141bb875 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b38c1911940..1d14cf131e6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -26,6 +26,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.ProbingActionTest; +import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; @@ -54,7 +56,7 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { From f61ac5d25c18521c488de15287edf4ad9cee88b0 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 5 Aug 2019 16:16:36 -0400 Subject: [PATCH 115/337] Refactored ProbingAction to minimize number of unnecessary methods --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 4 +- .../monitoring/blackbox/ProbingAction.java | 160 ++++++++---------- .../monitoring/blackbox/ProbingStep.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 4 +- .../blackbox/handlers/ActionHandler.java | 2 +- .../handlers/WebWhoisActionHandler.java | 7 +- .../blackbox/messages/HttpRequestMessage.java | 5 +- .../blackbox/ProbingActionTest.java | 130 +++++++------- .../blackbox/ProbingSequenceTest.java | 25 ++- .../monitoring/blackbox/ProbingStepTest.java | 6 + .../monitoring/blackbox/TestUtils.java | 2 +- .../handlers/WebWhoisActionHandlerTest.java | 11 +- 13 files changed, 178 insertions(+), 183 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 307afd34d81..e12d1f0f522 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; import java.util.Set; @@ -29,7 +30,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); + Set sequences = proberComponent.sequences(); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 1db97d1b581..fb83b236b69 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -49,7 +49,7 @@ EventLoopGroup provideEventLoopGroup() { /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides @Singleton - Class provideChannelClass() { + Class provideChannelClazz() { return NioSocketChannel.class; } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @@ -77,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - Set provideAllSequences(); + Set sequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index a8740e21c20..25c3a1c17d6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -33,10 +33,8 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -69,6 +67,8 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -85,6 +85,7 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ @@ -94,108 +95,89 @@ public abstract class ProbingAction implements Callable { public abstract String host(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } - /** - * The method that performs the work of the actual action. + * Performs the work of the actual action * - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ *

First, checks if channel is active by setting a listener to perform the bulk of the work + * when the connection future is successful.

+ * + *

Once the connection is successful, we establish which of the handlers in the pipeline is + * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when + * we receive an expected response from the server.

+ * + *

Next, we set a timer set to a specified delay. After the delay has passed, we send the + * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, + * we inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - - //ChannelPromise that we use to inform ProbingStep when we are finished. - ChannelPromise finished = channel().newPromise(); - - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - - return finished; - } /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws UndeterminedStateException { + public ChannelFuture call() { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); + + //Ensures channel has been set up with connection future as an attribute + checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + //When connection is established call super.call and set returned listener to success channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { + (ChannelFuture connectionFuture) -> { + if (connectionFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); + ActionHandler actionHandler; + try { + actionHandler = channel().pipeline().get(ActionHandler.class); + } catch (ClassCastException e) { + //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); + } + + ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> { + if (future.isSuccess()) { + finished.setSuccess(); + } else { + finished.setFailure(future.cause()); + } + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) { + logger.atInfo() + .log("Closed stale channel. Moving on to next ProbingStep"); + } else { + logger.atWarning() + .log( + "Could not close channel. Stale connection still exists."); + } + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); } else { //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( + logger.atSevere().withCause(connectionFuture.cause()).log( "Cannot connect to relay channel for %s channel: %s.", protocol().name(), this.channel()); ChannelFuture unusedFuture = channel().close(); @@ -228,7 +210,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract Protocol protocol(); - abstract Optional channel(); + abstract Channel channel(); abstract String host(); @@ -243,11 +225,11 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { + if (channel() == null) { bootstrap.handler( new ChannelInitializer() { @Override diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index ca980100067..3df536a9478 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -135,7 +135,7 @@ public void accept(Token token) { try { //call the generated action future = currentAction.call(); - } catch(UndeterminedStateException e) { + } catch(Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index c5e41fea38b..2e640338511 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -184,10 +184,10 @@ static SslClientInitializer provideSslClientInitializer(SslPro @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClass){ + Class channelClazz){ return new Bootstrap() .group(eventLoopGroup) - .channel(channelClass); + .channel(channelClazz); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 433604d6495..ab628ed064f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -46,7 +46,7 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler testHandlerProvider = new TestProvider<>(testHandler); private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - private ProbingAction newChannelAction; - private ProbingAction existingChannelAction; - private EmbeddedChannel channel; - private Protocol protocol; - /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** Sets up a {@link Protocol} corresponding to when a new connection is created */ - private void setupNewChannelProtocol() { - protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - } - /** Sets up a {@link Protocol} corresponding to when a new connection exists */ - private void setupExistingChannelProtocol() { - protocol = Protocol.builder() + + + + @Test + public void testBehavior_existingChannel() throws UndeterminedStateException { + //setup + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up a Protocol corresponding to when a connection exists. + Protocol protocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) .build(); - } - - /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ - private void setupNewChannelAction() { - newChannelAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - } - - private void setupChannel() { - channel = new EmbeddedChannel(); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ - private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ProbingAction.builder() + // Sets up a ProbingAction that creates a channel using test specified attributes. + ProbingAction action = ProbingAction.builder() .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) .setHost("") .build(); - } - - @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { - //setup - setupChannel(); - setupExistingChannelProtocol(); - channel.pipeline().addLast(conversionHandler); - channel.pipeline().addLast(testHandler); - setupExistingChannelAction(channel); + //tests main function of ProbingAction + ChannelFuture future = action.call(); - ChannelFuture future = existingChannelAction.call(); - - //Ensures that we pass in the right message to the channel and haven't marked the future as success yet - Object msg = channel.readOutbound(); + //Obtains the outboundMessage passed through pipeline after delay + Object msg = null; + while (msg == null) { + msg = channel.readOutbound(); + } + //tests the passed message is exactly what we expect assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - assertThat(response).isEqualTo(TEST_MESSAGE); - assertThat(future.isSuccess()).isFalse(); + String request = ((ByteBuf) msg).toString(UTF_8); + assertThat(request).isEqualTo(TEST_MESSAGE); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -158,18 +122,40 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { @Test public void testSuccess_newChannel() throws Exception { //setup - setupNewChannelProtocol(); + + LocalAddress address = new LocalAddress(ADDRESS_NAME); + Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + // Sets up a Protocol corresponding to when a new connection is created. + Protocol protocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) + .build(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - setupNewChannelAction(); - ChannelFuture future = newChannelAction.call(); + + // Sets up a ProbingAction with existing channel using test specified attributes. + ProbingAction action = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) + .build(); + + //tests main function of ProbingAction + ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.sync(); + future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()); + assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 8d9e45c6a66..e5f91a300d6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -18,27 +18,44 @@ import static google.registry.testing.JUnitBackports.assertThrows; import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.TestUtils.TestToken; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import java.net.SocketAddress; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; @RunWith(JUnit4.class) public class ProbingSequenceTest { private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new ProbingSequenceTestToken(); + private Token testToken = new TestToken("") { + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + }; + private void setupMock(ProbingStep mock, ProbingStep nextStep) { + Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + } /** * Custom {@link ProbingStep} subclass that acts as a mock * step, so we can test how well {@link ProbingSequence} builds * a linked list of {@link ProbingStep}s from their {@link Builder}s. */ + private static class TestStep extends ProbingStep { private String marker; @@ -92,9 +109,9 @@ public void specialAccept(Token token) { @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 73b104ae5dc..256eeb0b29d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -45,6 +45,7 @@ import javax.inject.Provider; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ public class ProbingStepTest { @@ -191,6 +192,11 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); + Object msg = channel.readOutbound(); + + while (msg == null) { + msg = channel.readOutbound(); + } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index cc8e1512fe9..ef9926a7620 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -204,7 +204,7 @@ public String toString() { } /** Basic outline for {@link Token} instances to be used in tests */ - private static abstract class TestToken extends Token { + static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 83d004d4555..f6123045683 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -41,7 +41,6 @@ import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; import org.joda.time.Duration; @@ -155,7 +154,8 @@ public void testBasic_responseOk() throws Exception { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -185,7 +185,8 @@ public void testBasic_responseFailure_badRequest() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); @@ -215,7 +216,7 @@ public void testBasic_responseFailure_badURL() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -248,7 +249,7 @@ public void testBasic_redirectCloseChannel() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early From 32359c8567046de6520a72d0f1eae4602abea72d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 15:45:32 -0400 Subject: [PATCH 116/337] Modified tests for WebWhois according to changes suggested by laijiang. --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 2 - .../monitoring/blackbox/ProbingAction.java | 1 - .../monitoring/blackbox/WebWhoisModule.java | 10 +- .../blackbox/ProbingActionTest.java | 20 +- .../blackbox/ProbingSequenceTest.java | 120 ++++------- .../monitoring/blackbox/ProbingStepTest.java | 187 ++++++++--------- .../blackbox/TestServers/TestServer.java | 38 ---- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 142 +------------ .../monitoring/blackbox/TokenTest.java | 59 ------ .../blackbox/handlers/ConversionHandler.java | 6 +- .../blackbox/handlers/NettyRule.java | 46 +++- .../handlers/SslClientInitializerTest.java | 5 - .../blackbox/handlers/TestActionHandler.java | 7 +- .../handlers/WebWhoisActionHandlerTest.java | 197 +++++++----------- .../blackbox/messages/TestMessage.java | 4 + .../blackbox/tokens/WebWhoisTokenTest.java | 2 + 18 files changed, 266 insertions(+), 589 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index e12d1f0f522..5ca423c29cc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -30,7 +29,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.sequences(); + ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index fb83b236b69..f9db4865f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,11 +14,9 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 25c3a1c17d6..0265390fafe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -138,7 +138,6 @@ public ChannelFuture call() { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); timer.newTimeout(timeout -> { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 2e640338511..de041afad38 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,14 +17,11 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -33,10 +30,7 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index b5d8f7599c4..ec5ee5d77ec 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,17 +20,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -39,9 +37,9 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; import javax.inject.Provider; import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,10 +72,9 @@ public class ProbingActionTest { public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - + @Ignore @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { + public void testBehavior_existingChannel() { //setup EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -95,7 +92,7 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost("") .build(); @@ -112,6 +109,9 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { String request = ((ByteBuf) msg).toString(UTF_8); assertThat(request).isEqualTo(TEST_MESSAGE); + // Ensures that we haven't marked future as done until response is received. + assertThat(future.isDone()).isFalse(); + //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); assertThat(future.isSuccess()).isTrue(); @@ -143,7 +143,7 @@ public void testSuccess_newChannel() throws Exception { .setBootstrap(bootstrap) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost(ADDRESS_NAME) .build(); @@ -151,7 +151,7 @@ public void testSuccess_newChannel() throws Exception { ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index e5f91a300d6..5c4452df7b3 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -15,17 +15,11 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; -import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; -import google.registry.monitoring.blackbox.TestUtils.TestToken; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import java.net.SocketAddress; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,85 +27,31 @@ @RunWith(JUnit4.class) public class ProbingSequenceTest { - private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new TestToken("") { - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - }; - - private void setupMock(ProbingStep mock, ProbingStep nextStep) { - Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + private ProbingStep setupMock() { + ProbingStep mock = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(mock).nextStep(); + return mock; } - /** - * Custom {@link ProbingStep} subclass that acts as a mock - * step, so we can test how well {@link ProbingSequence} builds - * a linked list of {@link ProbingStep}s from their {@link Builder}s. - */ - - private static class TestStep extends ProbingStep { - private String marker; - - /** We implement all abstract methods to simply return null, as we have no use for them here. */ - @Override - Duration duration() { - return null; - } - @Override - Protocol protocol() { - return null; - } + private static class Wrapper { - @Override - OutboundMessageType messageTemplate() { - return null; - } + T data; - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ - @Override - Bootstrap bootstrap() { - return null; - } - - public TestStep(String marker) { - this.marker = marker; - } - - /** - * On a call to accept, we modify the token to reflect what the current step is, so we can get - * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated - * in order. - */ - @Override - public void accept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - if (!isLastStep) { - nextStep().accept(token); - } else { - ((TestStep)nextStep()).specialAccept(token); - } - } - - /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ - public void specialAccept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - return; + public Wrapper(T data) { + this.data = data; } } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = Mockito.mock(ProbingStep.class); - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) @@ -119,16 +59,25 @@ public void testSequenceBasicConstruction_Success() { .addStep(thirdStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(thirdStep); + assertThat(thirdStep.nextStep()).isEqualTo(firstStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); + assertThat(wrapper.data).isTrue(); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(thirdStep) @@ -137,9 +86,16 @@ public void testSequenceAdvancedConstruction_Success() { .addStep(firstStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(firstStep); + assertThat(thirdStep.nextStep()).isEqualTo(secondStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); + assertThat(wrapper.data).isTrue(); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 256eeb0b29d..91a113940e8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,18 +11,19 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.TestUtils.dummyStep; -import static google.registry.monitoring.blackbox.TestUtils.testStep; -import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; import google.registry.monitoring.blackbox.TestUtils.TestProvider; @@ -30,19 +31,20 @@ import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; +import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; @@ -51,18 +53,18 @@ public class ProbingStepTest { /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final static String ADDRESS_NAME = "TEST_ADDRESS"; + private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final static int PROTOCOL_PORT = 0; + private final static String TEST_MESSAGE = "TEST_MESSAGE"; + private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -73,117 +75,108 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(ADDRESS_NAME); + /** + * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} + * is called, it just marks the supplied future as succeeded, returning the requisite token. + */ + private ProbingStep dummyStep() { + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(dummyStep).nextStep(); + return dummyStep; } - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); - dummyStep = dummyStep(eventLoopGroup); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - } + @Test + public void testNewChannel() throws Exception { + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() + // Sets up Protocol for when we create a new channel. + Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); - } - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) .build(); - } - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - //there should be no next step - assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); - } + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); - @Test - public void testNewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + //Set up blackbox server that receives our messages then echoes them back to us + nettyRule.setUpServer(address); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); + verify(dummyStep, times(1)).accept(any(Token.class)); } + @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupChannel(); - setupExistingChannelToken(); + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); + + // Sets up Protocol for when a channel already exists. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) + .build(); + + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) + .build(); + + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + + // Sets up an embedded channel to contain the two handlers we created already. + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + + //Assures that the channel has a succeeded connectionFuture. + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. + Token testToken = new ExistingChannelToken(channel, ""); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -200,17 +193,13 @@ public void testWithSequence_ExistingChannel() throws Exception { //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); + //At this point, we should have received the message, so the future obtained should be marked + // as a success + verify(dummyStep, times(1)).accept(any(Token.class)); - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index a4474b6b8b5..12e25a6bc6c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -14,24 +14,16 @@ package google.registry.monitoring.blackbox.TestServers; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; - import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform @@ -65,35 +57,5 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index e7f125bb906..4da75b31c25 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -74,7 +75,7 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends ChannelDuplexHandler { + static class RedirectHandler extends SimpleChannelInboundHandler { private String redirectInput; private String destinationInput; @@ -90,8 +91,7 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - HttpRequest request = (HttpRequest) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index ef9926a7620..2567a7cc155 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,42 +16,24 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMethod;; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.concurrent.DefaultPromise; -import java.net.SocketAddress; import javax.inject.Provider; -import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { - static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -76,33 +58,13 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); + response.headers().set("content-type", "text/plain"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); return response; } @@ -121,88 +83,6 @@ public E get() { } } - /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ - public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { - - String message; - - public DuplexMessageTest() { - message = ""; - } - - public DuplexMessageTest(String msg) { - message = msg; - } - - @Override - public String toString() { - return message; - } - - @Override - public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { - message = args[0]; - return this; - } - } - - /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .build(); - - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); - } - - /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { - private DefaultPromise future; - - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; - } - - @Override - public void accept(Token token) { - future.setSuccess(token); - } - public DefaultPromise getFuture() { - return future; - } - - @Override - public String toString() { - return "Dummy Step"; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; @@ -251,21 +131,5 @@ public Channel channel() { return channel; } } - - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java deleted file mode 100644 index 295bb809a13..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) - */ -@RunWith(JUnit4.class) -public class TokenTest { - - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - - public Token webToken = new WebWhoisToken(TEST_DOMAINS); - - @Test - public void testWebToken_MessageModificationSuccess() { - //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); - - //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { - throw new RuntimeException(e); - } - - - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 196141bb875..c9d337d6ad8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -32,7 +32,7 @@ * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +40,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 1d14cf131e6..86b54d9a07d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -25,14 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -44,7 +41,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -55,7 +51,7 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + *

Code based on and almost identical to {@code NettyRule} in the proxy. * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -83,10 +79,12 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + ImmutableList.builder().add(handlers).add(echoHandler).build()); } /** Sets up a client channel connecting to the give local address. */ @@ -124,7 +122,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertThatCustomWorks(String message) throws Exception { + public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -165,6 +163,38 @@ ThrowableSubject assertThatClientRootCause() { } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** + * Saves any inbound error as the cause of the promise failure. + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 83c8e132f07..523fb228752 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -22,12 +22,7 @@ import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 3ecbdcc0d06..95b06e623d1 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -25,17 +25,16 @@ */ public class TestActionHandler extends ActionHandler { - private String receivedMessage; + private InboundMessageType receivedMessage; @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage.toString(); + receivedMessage = inboundMessage; super.channelRead0(ctx, inboundMessage); } - @Override - public String toString() { + public InboundMessageType getResponse() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index f6123045683..d9d1a45ac6e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -20,7 +20,6 @@ import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; -import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; @@ -28,13 +27,11 @@ import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; @@ -56,6 +53,7 @@ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -65,11 +63,12 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of()) + private final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( + null, null, null, null)))) .setName("http") .setPersistentConnection(false) - .setPort(HTTPS_PORT) + .setPort(HTTP_PORT) .build(); @@ -78,14 +77,13 @@ public class WebWhoisActionHandlerTest { private ActionHandler actionHandler; private ProbingAction probingAction; private Provider actionHandlerProvider; + private Protocol initialProtocol; + private HttpRequestMessage msg; - private String generateLocalAddress(String addressString) { - String modifiedAddress = addressString + System.currentTimeMillis(); - address = new LocalAddress(modifiedAddress); - return modifiedAddress; - } - /** Creates default protocol with empty list of handlers and specified other inputs */ + /** + * Creates default protocol with empty list of handlers and specified other inputs + */ private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() .setName(name) @@ -95,7 +93,9 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect .build(); } - /** Initializes new WebWhoisActionHandler */ + /** + * Initializes new WebWhoisActionHandler + */ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, @@ -106,12 +106,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT actionHandlerProvider = new TestProvider<>(actionHandler); } - /** Sets up testing channel with requisite attributes */ + /** + * Sets up testing channel with requisite attributes + */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -119,18 +120,9 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .group(group) .channel(LocalChannel.class); } - /**Sets up probingAction for when testing redirection */ - private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setHost(TARGET_HOST) - .setChannel(channel) - .build(); - } - private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { + private void setupProbingActionWithoutChannel(Protocol protocol, + HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) @@ -140,170 +132,123 @@ private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMess .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + private void setupLocalServer(String redirectInput, String destinationInput, + EventLoopGroup group) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testBasic_responseOk() throws Exception { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { + msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, true); + initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + } + + @Test + public void testBasic_responseOk() { + //setup + setup("", null, true); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure_badRequest() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseBad", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage( + makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same assertThat(future.cause() instanceof FailureException).isTrue(); } - @Test - public void testBasic_responseFailure_badURL() { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseError", 0, true); - setupChannel(initialProtocol, msg); - - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, and event is success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); - } @Test - public void testBasic_redirectCloseChannel() { + public void testBasic_responseFailure_badURL() { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - //checks that future has not been set to successful or a failure - assertThat(testPromise.isSuccess()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - + //assesses that listener is triggered, and event is success + assertThat(future.isDone()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + //ensures Protocol is the same + assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_responseOk() throws UndeterminedStateException { - //setup + public void testAdvanced_redirect() { + // Sets up EventLoopGroup with 1 thread to be blocking. EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + // Sets up embedded channel. + setup("", makeBootstrap(group), false); + setupChannel(initialProtocol, msg); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); - } + // Initializes LocalAddress with unique String. + String host = TARGET_HOST + System.currentTimeMillis(); + address = new LocalAddress(host); - @Test - public void testAdvanced_responseFailure() throws UndeterminedStateException { - //setup - EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); + //stores future + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); + + // Sets up the local server that the handler will be redirected to. setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + FullHttpResponse response = + new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, + HTTP_REDIRECT + host, true, false)); + + //checks that future has not been set to successful or a failure + assertThat(future.isDone()).isFalse(); + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); //assesses that we successfully received good response and protocol is unchanged - assertThrows(FailureException.class, future::syncUninterruptibly); + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index 922c3052bda..c31a9d336bd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,6 +24,10 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; + public TestMessage() { + this(""); + } + public TestMessage(String msg) { message = msg; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index 9a3e755364b..bf5cfc45652 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -19,6 +19,8 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; From bd8fe963703b28ea72dcdc7bc8d9ac4be6d29040 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 16:42:43 -0400 Subject: [PATCH 117/337] Removed TestProvider from TestUtils. --- .../blackbox/ProbingActionTest.java | 7 ++-- .../monitoring/blackbox/ProbingStepTest.java | 11 ++---- .../blackbox/TestServers/TestServer.java | 3 -- .../monitoring/blackbox/TestUtils.java | 17 -------- .../handlers/WebWhoisActionHandlerTest.java | 39 +++++++------------ .../blackbox/messages/TestMessage.java | 4 -- 6 files changed, 20 insertions(+), 61 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index ec5ee5d77ec..f7857dd80f9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -64,8 +63,8 @@ public class ProbingActionTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + private Provider testHandlerProvider = () -> testHandler; + private Provider conversionHandlerProvider = () -> conversionHandler; /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -156,7 +155,7 @@ public void testSuccess_newChannel() throws Exception { future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 91a113940e8..1f09dd13553 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -90,9 +89,8 @@ private ProbingStep dummyStep() { @Test public void testNewChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when we create a new channel. Protocol testProtocol = Protocol.builder() @@ -142,9 +140,8 @@ public void testNewChannel() throws Exception { @Test public void testWithSequence_ExistingChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when a channel already exists. Protocol testProtocol = Protocol.builder() diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 12e25a6bc6c..46615a506fb 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -29,15 +29,12 @@ * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { - private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - this.localAddress = localAddress; - //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 2567a7cc155..50c60d9fc52 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -21,7 +21,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -29,7 +28,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Provider; /** Utility class for various helper methods used in testing. */ public class TestUtils { @@ -68,21 +66,6 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ - public static class TestProvider implements Provider { - - private E obj; - - public TestProvider(E obj) { - this.obj = obj; - } - - @Override - public E get() { - return obj; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index d9d1a45ac6e..cd85dd08df8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -22,10 +22,8 @@ import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; @@ -64,18 +62,16 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( - null, null, null, null)))) + .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( + null, null, null, null))) .setName("http") .setPersistentConnection(false) .setPort(HTTP_PORT) .build(); - private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; - private ProbingAction probingAction; private Provider actionHandlerProvider; private Protocol initialProtocol; private HttpRequestMessage msg; @@ -103,13 +99,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT STANDARD_PROTOCOL, messageTemplate ); - actionHandlerProvider = new TestProvider<>(actionHandler); + actionHandlerProvider = () -> actionHandler; } /** * Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + private void setupChannel(Protocol protocol) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -121,19 +117,8 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } - private void setupProbingActionWithoutChannel(Protocol protocol, - HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(addressString) - .build(); - } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group) { + EventLoopGroup group, LocalAddress address) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } @@ -148,7 +133,9 @@ private void setup(String hostName, Bootstrap bootstrap, boolean persistentConne public void testBasic_responseOk() { //setup setup("", null, true); - setupChannel(initialProtocol, msg); + + setupChannel(initialProtocol); + //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); @@ -168,7 +155,7 @@ public void testBasic_responseOk() { public void testBasic_responseFailure_badRequest() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -194,7 +181,7 @@ public void testBasic_responseFailure_badRequest() { public void testBasic_responseFailure_badURL() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -223,18 +210,18 @@ public void testAdvanced_redirect() { // Sets up embedded channel. setup("", makeBootstrap(group), false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); // Initializes LocalAddress with unique String. String host = TARGET_HOST + System.currentTimeMillis(); - address = new LocalAddress(host); + LocalAddress address = new LocalAddress(host); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group); + setupLocalServer("", host, group, address); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index c31a9d336bd..922c3052bda 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,10 +24,6 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; - public TestMessage() { - this(""); - } - public TestMessage(String msg) { message = msg; } From 33953662d025c85e82d4572c499e504023302c96 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 118/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 2 +- .../google/registry/xjc/package-info.java | 2 +- prober/build.gradle | 5 - .../monitoring/blackbox/NewChannelAction.java | 136 +++++++++ .../registry/monitoring/blackbox/Prober.java | 19 +- .../monitoring/blackbox/ProbingAction.java | 265 ++++++------------ .../handlers/ServerSideException.java | 15 + .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 117 +++----- .../blackbox/messages/HttpRequestMessage.java | 63 +---- .../messages/HttpResponseMessage.java | 44 +-- .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 15 files changed, 320 insertions(+), 365 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/prober/build.gradle b/prober/build.gradle index 478d33e1ef9..d0ac4ff3b51 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -20,8 +20,6 @@ dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] @@ -33,9 +31,6 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..0ba3a0c22be --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 5ca423c29cc..333330207f1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,26 +14,17 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 0265390fafe..2441debb12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,27 +14,14 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -47,7 +34,7 @@ import javax.inject.Provider; /** - * AutoValue class that represents action generated by {@link ProbingStep} + *Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -57,27 +44,36 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

*/ -@AutoValue + public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; + } /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); + /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -85,177 +81,92 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ - @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); - /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> finished.setSuccess(), + future -> { + if (!protocol().persistentConnection()) { + + //If we created a new channel for this action, close the connection to the channel + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } /** - * Performs the work of the actual action + * The method that sends the {@code outboundMessage} down the channel pipeline * - *

First, checks if channel is active by setting a listener to perform the bulk of the work - * when the connection future is successful.

- * - *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

- * - *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

- * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. + * @return future that denotes when the action has been successfully performed */ - - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override public ChannelFuture call() { - //ChannelPromise that we return - ChannelPromise finished = channel().newPromise(); - //Ensures channel has been set up with connection future as an attribute - checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); - - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture connectionFuture) -> { - if (connectionFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - - ActionHandler actionHandler; - try { - actionHandler = channel().pipeline().get(ActionHandler.class); - } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); - - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> { - if (future.isSuccess()) { - finished.setSuccess(); - } else { - finished.setFailure(future.cause()); - } - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) { - logger.atInfo() - .log("Closed stale channel. Moving on to next ProbingStep"); - } else { - logger.atWarning() - .log( - "Could not close channel. Stale connection still exists."); - } - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(connectionFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ - @AutoValue.Builder - public abstract static class Builder { - private Bootstrap bootstrap; - - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); } - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setHost(String value); - - public abstract Builder setChannel(Channel channel); - - abstract Protocol protocol(); + //ChannelPromise that we use to inform ProbingStep when we are finished. + ChannelPromise finished = channel().newPromise(); - abstract Channel channel(); + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } - abstract String host(); + return finished; + } - abstract ProbingAction autoBuild(); + public abstract static class Builder, P extends ProbingAction> { - public ProbingAction build() { - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - address = new LocalAddress(host()); - } + public abstract B delay(Duration value); - checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); - //If a channel is supplied, nothing is needed to be done + public abstract B outboundMessage(OutboundMessageType value); - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel() == null) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); + public abstract B protocol(Protocol value); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); + public abstract B host(String value); - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } + public abstract B path(String value); - //now we can actually build the ProbingAction - return autoBuild(); - } - } + public abstract P build(); - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); } /** @@ -265,27 +176,11 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - private static void addHandlers( + static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { channelPipeline.addLast(handlerProvider.get()); } } - - - - @Override - public String toString() { - return String.format( - "ProbingAction with delay: %d\n" + - "outboundMessage: %s\n" + - "protocol: %s\n" + - "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index 919006592ea..ac844ac99df 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,8 +15,7 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -90,8 +89,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - String host = channel.attr(REMOTE_ADDRESS_KEY).get(); + ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); + Protocol protocol = action.protocol(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -104,7 +103,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), host, protocol.port()); + .newHandler(channel.alloc(), action.host(), protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 34eac2a0118..21010f0e887 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,23 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -47,53 +48,30 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ - private final Bootstrap bootstrap; - - /** {@link Protocol} for when redirected to http endpoint. */ - private final Protocol httpWhoisProtocol; - - /** {@link Protocol} for when redirected to https endpoint. */ - private final Protocol httpsWhoisProtocol; - - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } + public WebWhoisActionHandler() {} /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { + throws ServerSideException { HttpResponseMessage response = (HttpResponseMessage) msg; + if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - //On success, we always pass message to ActionHandler's channelRead0 method. - super.channelRead0(ctx, msg); + finished.setSuccess(); + + logger.atInfo().log("Response Received: " + response); - } else if (response.headers().get("location") != null) { + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { //Obtain url to be redirected to URL url; @@ -101,68 +79,55 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); + int newPort = url.getDefaultPort(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, url.getDefaultPort(), newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException("Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); - } + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) .build(); + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } + logger.atInfo().log("Successfully Closed Connection"); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE + finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 5e9300d0f34..3fb8c187ad9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -19,28 +5,19 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; -/** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. - * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + @Override @@ -49,33 +26,15 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } - - /** Modifies headers to reflect new host and new path if applicable. */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) - setUri(args[1]); - - return this; + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + ByteBuf buf = request.content(); + if (buf == null) { + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - throw new IllegalArgumentException( - String.format( - "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + args, args.length)); + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - } - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index f1b2d6ac6a7..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,19 +6,33 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} - */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { + super(version, status); + } + + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); + + return finalResponse; } + + + } diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From f6d8a0ca90d394e2988ce6c13495c963c7a8c245 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:58:52 -0400 Subject: [PATCH 119/337] Fixed changes suggested by CydeWeys --- prober/build.gradle | 37 +-- .../monitoring/blackbox/Protocol.java | 87 +++++-- .../blackbox/exceptions/FailureException.java | 15 +- .../blackbox/handlers/ActionHandler.java | 91 +++---- .../handlers/WebWhoisActionHandlerTest.java | 222 ++++++++---------- 5 files changed, 224 insertions(+), 228 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index d0ac4ff3b51..259b093e35e 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,30 +16,35 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 624f08fd4e9..371b3c3e8d7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,28 +16,81 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; import javax.inject.Provider; /** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. + * Protocol Class packages all static variables necessary for a certain type of connection + * Both the host and the path can be changed for the same protocol + * Mainly packages the handlers necessary for the requisite channel pipeline */ @AutoValue public abstract class Protocol { - /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ - public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + + /** + * Default names associated with each protocol + */ + final static String EPP_PROTOCOL_NAME = "EPP"; + final static String DNS_PROTOCOL_NAME = "DNS"; + final static String WHOIS_PROTOCOL_NAME = "WHOIS"; + final static String RDAP_PROTOCOL_NAME = "RDAP"; + + private String host; + private String path = ""; + private ProbingAction probingAction; + + /** Setter method for Protocol's host*/ + public Protocol host(String host) { + this.host = host; + return this; + } + + /** Getter method for Protocol's host*/ + public String host() { + return host; + } + + /** Setter method for Protocol's path*/ + public Protocol path(String path) { + this.path = path; + return this; + } + + /** Getter method for Protocol's path*/ + public String path() { + return path; + } + /** Setter method for Protocol's ProbingAction parent*/ + public Protocol probingAction(ProbingAction probingAction) { + this.probingAction = probingAction; + return this; + } + + /** Getter method for Protocol's path*/ + public ProbingAction probingAction() { + return probingAction; + } + + /** If connection associated with Protocol is persistent, which is only EPP */ + public boolean persistentConnection() { + return name() == EPP_PROTOCOL_NAME; + } + + /** Protocol Name */ public abstract String name(); + /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - abstract ImmutableList> handlerProviders(); + public abstract ImmutableList> handlerProviders(); - /** Boolean that notes if connection associated with Protocol is persistent.*/ - abstract boolean persistentConnection(); + + public abstract Builder toBuilder(); public static Builder builder() { return new AutoValue_Protocol.Builder(); @@ -47,25 +100,13 @@ public static Builder builder() { @AutoValue.Builder public abstract static class Builder { - public abstract Builder setName(String value); - - public abstract Builder setPort(int num); + public abstract Builder name(String value); - public abstract Builder setHandlerProviders(ImmutableList> providers); + public abstract Builder port(int num); - public abstract Builder setPersistentConnection(boolean value); + public abstract Builder handlerProviders(ImmutableList> providers); public abstract Protocol build(); } - - @Override - public String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); - } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 36687e7ac82..9f716bb2589 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,18 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.exceptions; +package google.registry.monitoring.blackbox; -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class FailureException extends Exception { - - public FailureException(String msg) { - super(msg); - } - - public FailureException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index ab628ed064f..3fa60cd844a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,86 +15,69 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; +import com.google.common.flogger.StackSize; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.HttpResponse; +import java.util.function.Function; +import javax.inject.Inject; /** - *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

- * - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} - * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

- * - *

Subclasses specify further work to be done for specific kinds of channel pipelines.

+ * @param Generic Type of Inbound Message + * @param Generic Type of Outbound Message + * Abstract class that tells sends message down pipeline and + * and tells listeners to move on when the message is received. */ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +public abstract class ActionHandler extends SimpleChannelInboundHandler + implements Function { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link ChannelPromise} that informs {@link ProbingAction} if response has been received. */ - private ChannelPromise finished; + protected ChannelPromise finished; + private Channel channel; + - /** Returns initialized {@link ChannelPromise} to {@link ProbingAction}.*/ - public ChannelFuture getFinishedFuture() { + /** returns ChannelPromise for when inbound message is recieved + * a + * @param outboundMessage + * @return + */ + @Override + public ChannelFuture apply(O outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + + channel.writeAndFlush(outboundMessage); return finished; + + } + + public void resetFuture() { + finished = channel.newPromise(); } - /** Initializes {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { - // Once handler is added to channel pipeline, initialize channel and future for this handler + //Once handler is added to channel pipeline, initialize channel and future for this handler + + channel = ctx.channel(); finished = ctx.newPromise(); } - /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ + //Only purpose of Handler is to mark future as a success finished.setSuccess(); } - /** - * Logs the channel and pipeline that caused error, closes channel, then informs - * {@link ProbingAction} listeners of error. - */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atWarning().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); - - if (cause instanceof FailureException) { - //On FailureException, we know the response is a failure. - - //Since it wasn't a success, we still want to log to see what caused the FAILURE - logger.atInfo().log(cause.getMessage()); - - //As always, inform the ProbingStep that we successfully completed this action - finished.setFailure(cause); - - } else { - //On UndeterminedStateException, we know the response type is an error. - - //Since it wasn't a success, we still log what caused the ERROR - logger.atWarning().log(cause.getMessage()); - finished.setFailure(cause); - - //As this was an ERROR in performing the action, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } + logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } } + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index cd85dd08df8..63bb2cf5b53 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,43 +15,34 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelPromise; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@link WebWhoisActionHandler}. - * - *

Attempts to test how well {@link WebWhoisActionHandler} works - * when responding to all possible types of responses

- */ +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -59,183 +50,172 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; - private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( - null, null, null, null))) - .setName("http") - .setPersistentConnection(false) - .setPort(HTTP_PORT) - .build(); private EmbeddedChannel channel; private ActionHandler actionHandler; - private Provider actionHandlerProvider; - private Protocol initialProtocol; - private HttpRequestMessage msg; - - /** - * Creates default protocol with empty list of handlers and specified other inputs - */ - private Protocol createProtocol(String name, int port, boolean persistentConnection) { + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() - .setName(name) - .setPort(port) - .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) - .setPersistentConnection(persistentConnection) - .build(); + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); } - /** - * Initializes new WebWhoisActionHandler - */ - private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { - actionHandler = new WebWhoisActionHandler( - bootstrap, - STANDARD_PROTOCOL, - STANDARD_PROTOCOL, - messageTemplate - ); - actionHandlerProvider = () -> actionHandler; + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); } - /** - * Sets up testing channel with requisite attributes - */ + /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol) { + setupActionHandler(); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - private Bootstrap makeBootstrap(EventLoopGroup group) { - return new Bootstrap() - .group(group) - .channel(LocalChannel.class); + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group, LocalAddress address) { - WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); } - private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { - msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); - setupActionHandler(bootstrap, msg); - initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; } + @Test - public void testBasic_responseOk() { + public void testSuccess_responseOk() { //setup - setup("", null, true); - + Protocol initialProtocol = createProtocol("responseOk", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badRequest() { + public void testSuccess_responseBad() { //setup - setup("", null, false); + Protocol initialProtocol = createProtocol("responseBad", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage( - makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(future.isDone()).isTrue(); + assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badURL() { + public void testSuccess_redirectCloseChannel() { //setup - setup("", null, false); - setupChannel(initialProtocol); + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, and event is success - assertThat(future.isDone()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_redirect() { - // Sets up EventLoopGroup with 1 thread to be blocking. - EventLoopGroup group = new NioEventLoopGroup(1); - - // Sets up embedded channel. - setup("", makeBootstrap(group), false); - setupChannel(initialProtocol); - - // Initializes LocalAddress with unique String. - String host = TARGET_HOST + System.currentTimeMillis(); - LocalAddress address = new LocalAddress(host); + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group, address); - FullHttpResponse response = - new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + host, true, false)); + channel.writeInbound(originalResponse); - //checks that future has not been set to successful or a failure - assertThat(future.isDone()).isFalse(); + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); - channel.writeInbound(response); + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } + } From 189423e0fbcb628794f64a4541b12260a513e55c Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 120/337] Added missing license headers and JavaDoc --- .../handlers/ServerSideException.java | 16 ++++++- .../blackbox/messages/HttpRequestMessage.java | 45 ++++++++++++++----- .../messages/HttpResponseMessage.java | 32 ++++++++++--- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java index 5d3addb920e..441062a9e7b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; /** @@ -12,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 3fb8c187ad9..8fbb55c6339 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,13 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} + * (but needs to implement {@link OutboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion + * from {@link FullHttpRequest} to its type

+ */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +35,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,15 +42,22 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - if (buf == null) { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //creates message based on content found in original request + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //stores headers from request in finalRequest + request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); + + return finalRequest; + + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..776e7de0824 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,11 +1,33 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} + * (but needs to implement {@link InboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion + * from {@link FullHttpResponse} to its type

+ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -17,22 +39,20 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } + /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); + //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + //stores headers from response in finalResponse + response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); return finalResponse; } - - - } From 474cbce403bff38fa955b776718351e7c6cd57cf Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 121/337] Minor fix in NewChannelAction JavaDoc --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..1e7578d5679 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; - import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -28,8 +27,7 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) */ @AutoValue public abstract class NewChannelAction extends ProbingAction { From 9695519aa87d13402c31c539b75c825f54b1ff2d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 13:33:23 -0400 Subject: [PATCH 122/337] Minor Style Fix --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 ---- .../java/google/registry/monitoring/blackbox/Protocol.java | 1 - .../registry/monitoring/blackbox/handlers/ActionHandler.java | 1 - .../monitoring/blackbox/handlers/WebWhoisActionHandler.java | 2 -- 4 files changed, 8 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..84cf75492f2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -52,7 +52,6 @@ public Channel channel() { return this.channel; } - @Override public abstract Builder toBuilder(); @@ -120,7 +119,6 @@ public static NewChannelAction.Builder builder() return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -129,6 +127,4 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 371b3c3e8d7..4b0727229c1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -109,4 +109,3 @@ public abstract static class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 3fa60cd844a..503d211b324 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -80,4 +80,3 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 21010f0e887..5b77461cd8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -131,7 +131,5 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } } - - } From dfc8401a3f5ad3e5fb318d11adb49d0782e579d7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 123/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 70 ++--- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 17 +- .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProberModule.java | 83 ++++-- .../monitoring/blackbox/ProbingAction.java | 17 +- .../monitoring/blackbox/ProbingSequence.java | 117 +++++---- .../monitoring/blackbox/ProbingStep.java | 177 ++++++------- .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 12 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 ++++ .../monitoring/blackbox/WebWhoisModule.java | 170 ++++++------ .../exceptions/EppClientException.java | 29 ++ .../exceptions/InternalException.java | 29 ++ .../exceptions/ResponseException.java | 29 ++ .../ServerSideException.java | 4 +- .../blackbox/handlers/ActionHandler.java | 88 ++++--- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/WebWhoisActionHandler.java | 19 +- .../handlers/WebWhoisMessageHandler.java | 31 +-- .../blackbox/messages/HttpRequestMessage.java | 50 +--- .../messages/HttpResponseMessage.java | 32 +-- .../messages/OutboundMessageType.java | 11 +- .../blackbox/ProbingActionTest.java | 158 +++++------ .../blackbox/ProbingSequenceStepTest.java | 219 ++++++++++++++++ .../blackbox/TestServers/TestServer.java | 57 ++-- .../blackbox/TestServers/WebWhoisServer.java | 33 +-- .../monitoring/blackbox/TestUtils.java | 144 +++++++++- .../monitoring/blackbox/TokenTest.java | 60 +++++ .../blackbox/handlers/ConversionHandler.java | 11 +- .../blackbox/handlers/NettyRule.java | 62 +---- .../handlers/SslClientInitializerTest.java | 49 +++- .../blackbox/handlers/TestActionHandler.java | 15 +- .../handlers/WebWhoisActionHandlerTest.java | 247 +++++++++++++----- 36 files changed, 1589 insertions(+), 712 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/build.gradle b/prober/build.gradle index 259b093e35e..e48eacb8bf9 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -17,40 +17,42 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { - def deps = rootProject.dependencyMap - - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - - runtime deps['com.google.flogger:flogger-system-backend'] - runtime deps['com.google.auto.value:auto-value'] - runtime deps['io.netty:netty-tcnative-boringssl-static'] - - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') - - // Include auto-value in compile until nebula-lint understands - // annotationProcessor - annotationProcessor deps['com.google.auto.value:auto-value'] - testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] + def deps = rootProject.dependencyMap + + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] + + runtime deps['com.google.flogger:flogger-system-backend'] + runtime deps['com.google.auto.value:auto-value'] + runtime deps['io.netty:netty-tcnative-boringssl-static'] + + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') + //testCompile project(path: ':core', configuration: 'testRuntime') + + // Include auto-value in compile until nebula-lint understands + // annotationProcessor + annotationProcessor deps['com.google.auto.value:auto-value'] + testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 84cf75492f2..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -52,6 +53,7 @@ public Channel channel() { return this.channel; } + @Override public abstract Builder toBuilder(); @@ -83,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -116,9 +118,10 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } + @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -127,4 +130,6 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } + } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 333330207f1..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,16 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index f9db4865f78..73bd9127852 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,68 +14,99 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import io.netty.channel.Channel; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SslProvider; import java.util.Set; import javax.inject.Singleton; -import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores - * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. + * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} + * + *

Provides

*/ @Module public class ProberModule { + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; - /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - - /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides - @Singleton - Class provideChannelClazz() { - return NioSocketChannel.class; + @HttpWhoisProtocol + ProbingSequence provideHttpWhoisSequence( + @HttpWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ + @Provides - @Singleton - Duration provideDuration() { - return DEFAULT_DURATION; + @HttpsWhoisProtocol + ProbingSequence provideHttpsWhoisSequence( + @HttpsWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; + } + + @Provides + @HttpsWhoisProtocol + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } - /** Root level {@link Component} that provides each {@link ProbingSequence}. */ + @Provides + ImmutableMap providePortToProtocolMap( + Set protocolSet) { + return Maps.uniqueIndex(protocolSet, Protocol::port); + } + + + @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, + TokenModule.class }) public interface ProberComponent { - //Standard WebWhois sequence - Set sequences(); + @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); + + @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); + + ImmutableMap providePortToProtocolMap(); + + @WebWhoisProtocol Token provideWebWhoisToken(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2441debb12d..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -34,7 +34,7 @@ import javax.inject.Provider; /** - *Superclass that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -183,4 +183,19 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + @Override + public String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n" + + "path: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host(), + path() + ); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 91c4165c068..6387207fea4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,86 +14,109 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. + * Represents Sequence of {@link ProbingSteps} that the Prober performs in order * + * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} + * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /**Each {@link ProbingSequence} requires a start token to begin running. */ - private Token startToken; + /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ + private EventLoopGroup eventGroup; - public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ + private Bootstrap bootstrap; + + public Bootstrap getBootstrap() { + return bootstrap; + } + + public void start(Token token) { + // calls the first step with input token; + firstStep.accept(token); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * {@link Builder} which takes in {@link ProbingStep}s + * + * @param Same specified {@code C} for overall {@link ProbingSequence} */ - public static class Builder { - - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - - private Token startToken; - - public Builder(Token startToken) { - this.startToken = startToken; + public static class Builder { + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstSequenceStep; + private EventLoopGroup eventLoopGroup; + private Class classType; + + Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; + return this; } - /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, - * built, and pointed to by the previous {@link ProbingStep} added. - */ - public Builder addStep(ProbingStep step) { - - if (currentStep == null) + Builder addStep(ProbingStep step) { + if (currentStep == null) { firstStep = step; - else + } else { currentStep.nextStep(step); - + } currentStep = step; return this; } - /** We take special note of the first repeated step. */ - public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; + /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ + Builder makeFirstRepeated() { + firstSequenceStep = currentStep; + return this; + } + /** Set the class to be the same as {@code C} */ + public Builder setClass(Class classType) { + this.classType = classType; return this; } - /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and - * calls private constructor to create {@link ProbingSequence}. - */ - public ProbingSequence build() { - if (firstRepeatedStep == null) - firstRepeatedStep = firstStep; - - currentStep.nextStep(firstRepeatedStep); + public ProbingSequence build() { + currentStep.nextStep(firstSequenceStep); currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); } + } - private ProbingSequence(ProbingStep firstStep, Token startToken) { + /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ + private void setParents() { + ProbingStep currentStep = firstStep.parent(this).nextStep(); + + while (currentStep != firstStep) { + currentStep = currentStep.parent(this).nextStep(); + } + } + private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, + Class classType) { this.firstStep = firstStep; - this.startToken = startToken; + this.eventGroup = eventLoopGroup; + this.bootstrap = new Bootstrap() + .group(eventGroup) + .channel(classType); + setParents(); + } + + @Override + public String toString() { + return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 3df536a9478..5bad5abf6bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,164 +14,155 @@ package google.registry.monitoring.blackbox; -import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.io.IOException; import java.util.function.Consumer; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step - * in {@link ProbingSequence}. + * Represents generator of actions performed at each step in {@link ProbingSequence} + * + * @param See {@code C} in {@link ProbingSequence} * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. - * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, - * generates a new {@link ProbingAction} to call.

+ * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies + * these components on each loop iteration with the consumed {@link Token} and from that, + * generates new {@link ProbingAction} to perform<./p> * + *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -@AutoValue -public abstract class ProbingStep implements Consumer { +public abstract class ProbingStep implements Consumer { + public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); + protected static final Duration DEFAULT_DURATION = new Duration(2000L); private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Necessary boolean to inform when to obtain next {@link Token}*/ - protected boolean isLastStep = false; - private ProbingStep nextStep; - - /** Time delay duration between actions. */ - abstract Duration duration(); - - /** {@link Protocol} type for this step. */ - abstract Protocol protocol(); - - /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ - abstract OutboundMessageType messageTemplate(); - - /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ - abstract Bootstrap bootstrap(); - + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + protected LocalAddress address = DEFAULT_ADDRESS; - @AutoValue.Builder - public static abstract class Builder { - public abstract Builder setDuration(Duration value); + /** Necessary boolean to inform when to obtain next {@link Token}*/ + private boolean isLastStep = false; + private ProbingStep nextStep; + private ProbingSequence parent; - public abstract Builder setProtocol(Protocol value); + protected Duration duration; - public abstract Builder setMessageTemplate(OutboundMessageType value); + protected final Protocol protocol; + protected final OutboundMessageType message; - public abstract Builder setBootstrap(Bootstrap value); + protected ProbingStep(Protocol protocol, OutboundMessageType message) { + this.protocol = protocol; + this.message = message; + } - public abstract ProbingStep build(); + private OutboundMessageType message() { + return message; } - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); + Protocol protocol() { + return protocol; } + void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { - OutboundMessageType message = token.modifyMessage(messageTemplate()); - ProbingAction.Builder probingActionBuilder = ProbingAction.builder() - .setDelay(duration()) - .setProtocol(protocol()) - .setOutboundMessage(message) - .setHost(token.host()); - - if (token.channel() != null) - probingActionBuilder.setChannel(token.channel()); - else - probingActionBuilder.setBootstrap(bootstrap()); - - return probingActionBuilder.build(); + ProbingStep parent(ProbingSequence parent) { + this.parent = parent; + return this; } + /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + private ProbingAction generateAction(Token token) throws InternalException { + ProbingAction generatedAction; + + OutboundMessageType message = token.modifyMessage(message()); + + //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction + if (protocol().persistentConnection() && token.channel() != null) { + generatedAction = ExistingChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .channel(token.channel()) + .build(); + } else { + generatedAction = NewChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .bootstrap(parent.getBootstrap()) + .address(address) + .build(); + + } + return generatedAction; + } - /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ + + /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

- */ @Override public void accept(Token token) { - ProbingAction currentAction; + ProbingAction nextAction; //attempt to generate new action. On error, move on to next step try { - currentAction = generateAction(token); - } catch(UndeterminedStateException e) { + nextAction = generateAction(token); + } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch(Exception e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; + //If the next step maintains the connection, pass on the channel from this + if (protocol().persistentConnection()) { + token.channel(nextAction.channel()); } + //call the created action + ChannelFuture future = nextAction.call(); + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - + nextStep.accept(generateNextToken(token)); } else { - //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - - if (protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n", + "OutboundMessage: %s\n" + + "and parent sequence: %s", protocol(), - messageTemplate().getClass().getName()); + message(), + parent); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 4b0727229c1..24c666b8d9d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -108,4 +108,16 @@ public abstract static class Builder { public abstract Protocol build(); } + + @Override + public String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index de041afad38..dba905c0e49 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,96 +18,90 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; + +import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; - private static final String HTTP_PROTOCOL_NAME = "http"; - private static final String HTTPS_PROTOCOL_NAME = "https"; - - /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ - private static final int maximumMessageLengthBytes = 512 * 1024; + final static String DOMAIN_SUFFIX = "whois.nic."; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpWhoisProtocol {} + @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpsWhoisProtocol {} + @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - /** {@link Provides} standard WebWhois sequence. */ + + + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + + @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { + @HttpWhoisProtocol + static ProbingStep provideHttpWhoisProbingSequence( + @HttpWhoisProtocol Protocol httpWhoisProtocol) { + return new ProbingStepWeb<>(httpWhoisProtocol); + } - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); + @Provides + @HttpsWhoisProtocol + static ProbingStep provideHttpsWhoisProbingStep( + @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { + return new ProbingStepWeb<>(httpsWhoisProtocol); } - /** {@link Provides} only step used in WebWhois sequence. */ + @Singleton @Provides - @WebWhoisProtocol - static ProbingStep provideWebWhoisStep( - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @WebWhoisProtocol Bootstrap bootstrap, - HttpRequestMessage messageTemplate, - Duration duration) { - - return ProbingStep.builder() - .setProtocol(httpWhoisProtocol) - .setBootstrap(bootstrap) - .setMessageTemplate(messageTemplate) - .setDuration(duration) + @HttpWhoisProtocol + static Protocol provideHttpWhoisProtocol( + @HttpWhoisProtocol int httpWhoisPort, + @HttpWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides - @HttpWhoisProtocol - static Protocol provideHttpWhoisProtocol( + @IntoSet + static Protocol provideHttpProtocolForSet( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTP_PROTOCOL_NAME) - .setPort(httpWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ + @Singleton @Provides @HttpsWhoisProtocol @@ -115,21 +109,40 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTPS_PROTOCOL_NAME) - .setPort(httpsWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } + @Singleton + @Provides + @IntoSet + static Protocol provideHttpsProtocolForSet( + @HttpsWhoisProtocol int httpsWhoisPort, + @HttpsWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Provides + @WebWhoisProtocol + String provideHttpWhoisHost() { + return "app"; + } + - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -138,14 +151,13 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -155,60 +167,34 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } - @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); - } - - @Provides - static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { - return new HttpObjectAggregator(maxContentLength); - } - - /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ - @Provides - @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); - } - /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ - @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap( - EventLoopGroup eventLoopGroup, - Class channelClazz){ - return new Bootstrap() - .group(eventLoopGroup) - .channel(channelClazz); + static MessageHandler provideMessageHandler() { + return new WebWhoisMessageHandler(); } @Provides - @WebWhoisProtocol - int provideMaximumMessageLengthBytes() { - return maximumMessageLengthBytes; + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); } - /** {@link Provides} the list of top level domains to be probed */ - @Singleton @Provides - @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); + static HttpObjectAggregator provideHttpObjectAggregator() { + return new HttpObjectAggregator(1048576); } @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return HTTP_WHOIS_PORT; + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } @Provides @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return HTTPS_WHOIS_PORT; + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 503d211b324..7898203e92d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,68 +15,88 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import com.google.common.flogger.StackSize; -import io.netty.channel.ChannelInboundHandlerAdapter; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpResponse; -import java.util.function.Function; -import javax.inject.Inject; /** + *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - * @param Generic Type of Inbound Message - * @param Generic Type of Outbound Message - * Abstract class that tells sends message down pipeline and - * and tells listeners to move on when the message is received. + *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

+ * + *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} + * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception + * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses + * specify further work to be done for specific kinds of channel pipelines.

*/ -public abstract class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - protected ChannelPromise finished; - private Channel channel; + /** Three types of responses received down pipeline */ + public enum ResponseType {SUCCESS, FAILURE, ERROR} + /** Status of response for current {@link ActionHandler} instance */ + private static ResponseType status; - /** returns ChannelPromise for when inbound message is recieved - * a - * @param outboundMessage - * @return - */ - @Override - public ChannelFuture apply(O outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline + protected ChannelPromise finished; - channel.writeAndFlush(outboundMessage); + /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + public ChannelFuture getFuture() { return finished; - - } - - public void resetFuture() { - finished = channel.newPromise(); } + /** Initializes new {@link ChannelPromise} */ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler - - channel = ctx.channel(); finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ - //Only purpose of Handler is to mark future as a success - + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + //simply marks finished as success + status = ResponseType.SUCCESS; finished.setSuccess(); } + /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); + logger.atSevere().withCause(cause).log(String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), + ctx.channel().pipeline().toString())); + + + if (ResponseException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + status = ResponseType.FAILURE; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (ServerSideException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + status = ResponseType.ERROR; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (InternalException.class.isInstance(cause)){ + logger.atSevere().withCause(cause).log("Severe internal error"); + finished.setFailure(cause); + } else { + finished.setFailure(cause); + } + + //due to failure, close channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 5b77461cd8f..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -17,20 +17,16 @@ import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; @@ -59,7 +55,7 @@ public WebWhoisActionHandler() {} */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ServerSideException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -67,9 +63,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - finished.setSuccess(); - logger.atInfo().log("Response Received: " + response); + super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -79,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -126,10 +121,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + throw new ResponseException("Response received from remote site was: " + response.status()); } } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 58c395ad86e..4afc5d95ba7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,52 +1,33 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -/** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} - * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection. - */ -public class WebWhoisMessageHandler extends ChannelDuplexHandler { +public class WebWhoisMessageHandler extends MessageHandler { + + private HttpRequestMessage request; @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - HttpRequestMessage request = (HttpRequestMessage) msg; + request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + FullHttpResponse originalResponse = (FullHttpResponse) msg; - HttpResponseMessage response = new HttpResponseMessage(originalResponse); + InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8fbb55c6339..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,13 +6,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} - * (but needs to implement {@link OutboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion - * from {@link FullHttpRequest} to its type

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -35,6 +14,11 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + + @Override public HttpRequestMessage setUri(String path) { @@ -42,22 +26,16 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - - //creates message based on content found in original request - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - - - //stores headers from request in finalRequest - request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - - return finalRequest; - + HttpRequestMessage output; + if (buf == null) { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + } else { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + } + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 776e7de0824..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,33 +1,11 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} - * (but needs to implement {@link InboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion - * from {@link FullHttpResponse} to its type

- */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -39,20 +17,22 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } - /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); - //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - //stores headers from response in finalResponse - response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); return finalResponse; } + + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 6e3da3f69d2..0dd17e9d4a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,17 +14,8 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; - /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType { - - /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; +public interface OutboundMessageType {} - /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - @Override - String toString(); -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index f7857dd80f9..cbcf2fc82b0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,19 +15,20 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -38,7 +39,6 @@ import io.netty.channel.nio.NioEventLoopGroup; import javax.inject.Provider; import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,65 +51,99 @@ * */ @RunWith(JUnit4.class) public class ProbingActionTest { - private static final String TEST_MESSAGE = "MESSAGE_TEST"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final int TEST_PORT = 0; - - private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + /** Necessary Constants for test */ + private final String TEST_MESSAGE = "MESSAGE_TEST"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final int TEST_PORT = 0; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = () -> testHandler; - private Provider conversionHandlerProvider = () -> conversionHandler; + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + private ProbingAction newChannelAction; + private ProbingAction existingChannelAction; + private EmbeddedChannel channel; + private Protocol protocol; /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); + /** Sets up a {@link Protocol} corresponding to when a new connection is created */ + private void setupNewChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(false) + .build(); + } + /** Sets up a {@link Protocol} corresponding to when a new connection exists */ + private void setupExistingChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(true) + .build(); + } + + /** Sets up a {@link NewChannelAction} with test specified attributes */ + private void setupNewChannelAction() { + newChannelAction = NewChannelAction.builder() + .bootstrap(bootstrap) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .address(address) + .build(); + } + + private void setupChannel() { + channel = new EmbeddedChannel(); + } + + /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + private void setupExistingChannelAction(Channel channel) { + existingChannelAction = ExistingChannelAction.builder() + .channel(channel) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .build(); + } - @Ignore @Test public void testBehavior_existingChannel() { //setup - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up a Protocol corresponding to when a connection exists. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(true) - .build(); + setupChannel(); + setupExistingChannelProtocol(); + setupExistingChannelAction(channel); + channel.pipeline().addLast(conversionHandler); + channel.pipeline().addLast(testHandler); - // Sets up a ProbingAction that creates a channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setChannel(channel) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost("") - .build(); - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = existingChannelAction.call(); - //Obtains the outboundMessage passed through pipeline after delay - Object msg = null; - while (msg == null) { - msg = channel.readOutbound(); - } - //tests the passed message is exactly what we expect + //Ensures that we pass in the right message to the channel and haven't marked the future as success yet + Object msg = channel.readOutbound(); assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - assertThat(request).isEqualTo(TEST_MESSAGE); - - // Ensures that we haven't marked future as done until response is received. - assertThat(future.isDone()).isFalse(); + String response = ((ByteBuf) msg).toString(UTF_8); + assertThat(response).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()).isFalse(); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); @@ -121,41 +155,19 @@ public void testBehavior_existingChannel() { @Test public void testSuccess_newChannel() throws Exception { //setup - - LocalAddress address = new LocalAddress(ADDRESS_NAME); - Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); - - // Sets up a Protocol corresponding to when a new connection is created. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - + setupNewChannelProtocol(); + setupNewChannelAction(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - // Sets up a ProbingAction with existing channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.syncUninterruptibly(); + future.sync(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()); + assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java new file mode 100644 index 00000000000..7a713017072 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java @@ -0,0 +1,219 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.TestUtils.TestStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.handlers.ConversionHandler; +import google.registry.monitoring.blackbox.handlers.NettyRule; +import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.junit.Rule; +import org.junit.Test; + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + + /** Used for testing how well probing step can create connection to blackbox server */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + + + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ + private ProbingSequence testSequence; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); + dummyStep = new DummyStep(testProtocol, eventLoopGroup); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(false) + .build(); + } + + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(true) + .build(); + } + + /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ + private void setupSequence() { + testSequence = new ProbingSequence.Builder() + .eventLoopGroup(eventLoopGroup) + .setClass(LocalChannel.class) + .addStep(firstStep) + .makeFirstRepeated() + .addStep(dummyStep) + .build(); + } + + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //there should be no next step + assertThat(firstStep.nextStep()).isNull(); + + //we expect that this exception be thrown + assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); + + } + + @Test + public void testWithSequence_NewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupSequence(); + setupNewChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupSequence(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 46615a506fb..67e2cb7165d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,40 +1,37 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform */ public abstract class TestServer { + private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + this.localAddress = localAddress; + //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override @@ -54,5 +51,35 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** Saves any inbound error as the cause of the promise failure. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 4da75b31c25..ab9997b6c68 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -19,13 +5,11 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -36,10 +20,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - *

It will either redirect the client to the correct location if given the + * It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location

+ * an unexpected host location */ public class WebWhoisServer extends TestServer { @@ -75,14 +59,14 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { + static class RedirectHandler extends ChannelDuplexHandler { private String redirectInput; private String destinationInput; /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; @@ -91,14 +75,15 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { + public void channelRead(ChannelHandlerContext ctx, Object msg) { + HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 50c60d9fc52..8d1722c9625 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,24 +14,47 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { + static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -56,19 +79,102 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain"); + response.headers().set("content-type", "text/plain").set("content-length", "0"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; + } + + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); return response; } + /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ + public static class TestProvider implements Provider { + + private E obj; + + public TestProvider(E obj) { + this.obj = obj; + } + + @Override + public E get() { + return obj; + } + } + + /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ + public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { + + String message; + + public DuplexMessageTest() { + message = ""; + } + + public DuplexMessageTest(String msg) { + message = msg; + } + + @Override + public String toString() { + return message; + } + } + + /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ + public static class TestStep extends ProbingStep { + + public TestStep(Protocol protocol, String testMessage, LocalAddress address) { + super(protocol, new DuplexMessageTest(testMessage)); + this.address = address; + this.duration = Duration.ZERO; + } + } + + /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ + public static class DummyStep extends ProbingStep { + private DefaultPromise future; + + public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { + super(protocol, new DuplexMessageTest()); + future = new DefaultPromise(eventLoopGroup.next()) {}; + duration = Duration.ZERO; + } + + @Override + public void accept(Token token) { + future.setSuccess(token); + } + public DefaultPromise getFuture() { + return future; + } + } + /** Basic outline for {@link Token} instances to be used in tests */ - static abstract class TestToken extends Token { - protected String host; + private static abstract class TestToken extends Token { + private String host; protected TestToken(String host) { this.host = host; @@ -84,7 +190,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String host() { + public String getHost() { return host; } @@ -114,5 +220,33 @@ public Channel channel() { return channel; } } + + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java new file mode 100644 index 00000000000..ef5cba5b60d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -0,0 +1,60 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + */ +@RunWith(JUnit4.class) +public class TokenTest { + + private static String PREFIX = "whois.nic."; + private static String TEST_STARTER = "starter"; + private static String TEST_DOMAIN = "test"; + + public Token webToken = new WebWhoisToken(TEST_DOMAIN); + + @Test + public void testWebToken_MessageModificationSuccess() { + //creates Request message with header + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + message.headers().set("host", TEST_STARTER); + + //attempts to use Token's method for modifying the method based on its stored host + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { + throw new RuntimeException(e); + } + + + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index c9d337d6ad8..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,13 +17,10 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -31,8 +28,8 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 86b54d9a07d..b6b5e8fbe0c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -25,11 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingActionTest; -import google.registry.monitoring.blackbox.ProbingStepTest; -import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -41,6 +41,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -51,8 +52,8 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

+ *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -79,19 +80,16 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { + public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, - ImmutableList.builder().add(handlers).add(echoHandler).build()); + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); } /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - Protocol protocol, - String host, + ProbingAction probingAction, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -111,9 +109,7 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol) - .attr(REMOTE_ADDRESS_KEY, host); - + .attr(PROBING_ACTION_KEY, probingAction); channel = b.connect(localAddress).syncUninterruptibly().channel(); } @@ -122,7 +118,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertReceivedMessage(String message) throws Exception { + public void assertThatCustomWorks(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -163,38 +159,6 @@ ThrowableSubject assertThatClientRootCause() { } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** - * Saves any inbound error as the cause of the promise failure. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 523fb228752..469c62a8f75 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,14 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.ExistingChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; @@ -41,6 +45,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; +import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -62,6 +67,8 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { + private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); + /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -86,12 +93,15 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private final static Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .persistentConnection(false) + .build(); + + private ProbingAction probingAction; private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -103,13 +113,23 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } + private void setupProbingAction(Channel channel) { + probingAction = ExistingChannelAction.builder() + .delay(Duration.ZERO) + .host(SSL_HOST) + .channel(channel) + .outboundMessage(DEFAULT_MESSAGE) + .protocol(PROTOCOL) + .build(); + } + @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - channel.attr(PROTOCOL_KEY).set(PROTOCOL); - channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); + setupProbingAction(channel); + channel.attr(PROBING_ACTION_KEY).set(probingAction); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -140,7 +160,8 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -168,7 +189,8 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -197,7 +219,8 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 95b06e623d1..518bb9ba686 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,7 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -23,18 +22,18 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ - private InboundMessageType receivedMessage; + private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage; + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } - public InboundMessageType getResponse() { + @Override + public String toString() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 63bb2cf5b53..d8a672758da 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,32 +15,44 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; +import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ +/** + * Unit tests for {@link WebWhoisActionHandler}. + * + *

Attempts to test how well {@link WebWhoisActionHandler} works + * when responding to all possible types of responses

+ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; @@ -50,89 +62,96 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; + private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); + private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - + private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; + private ProbingAction probingAction; + private Provider actionHandlerProvider; + private void generateLocalAddress() { + address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + } /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { + private Protocol createProtocol(String name, int port) { return Protocol.builder() .name(name) .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); + .handlerProviders(ImmutableList.of(actionHandlerProvider)) + .persistentConnection(false) + .build(); } /** Initializes new WebWhoisActionHandler */ private void setupActionHandler() { actionHandler = new WebWhoisActionHandler(); + actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); + private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + setupProbingActionBasic( + protocol, + outboundMessage, + makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); + channel.attr(PROBING_ACTION_KEY).set(probingAction); } + private Bootstrap makeBootstrap(EventLoopGroup group) { + return new Bootstrap() + .group(group) + .channel(LocalChannel.class); + } /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() + private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + probingAction = NewChannelAction.builder() .protocol(protocol) .outboundMessage(outboundMessage) .delay(DEFAULT_DURATION) .bootstrap(bootstrap) + .host(TARGET_HOST) + .address(DEFAULT_ADDRESS) .build(); } - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); + private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(host) + .address(address) + .build(); } - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; + private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testSuccess_responseOk() { + public void testBasic_responseOk() throws Exception { //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -140,25 +159,30 @@ public void testSuccess_responseOk() { channel.writeInbound(response); - //assesses that we successfully receivved good response and protocol is unchanged + //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testSuccess_responseBad() { + public void testBasic_responseFailure() { //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseBad", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + FullHttpResponse response = HttpResponseMessage + .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -167,24 +191,63 @@ public void testSuccess_responseBad() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + } + @Test + public void testBasic_responseError() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseError", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + + //stores future + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, and event is success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testSuccess_redirectCloseChannel() { + public void testBasic_redirectCloseChannel() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); + HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", 0); + generateLocalAddress(); + setupChannel(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(outboundMessage); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + //checks that future has not been set to successful or a failure + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); @@ -195,27 +258,69 @@ public void testSuccess_redirectCloseChannel() { } @Test - public void testSuccess_redirectHost() { + public void testBasic_redirectHost() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); channel.writeInbound(originalResponse); + ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); + Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); + assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); + } + + @Test + public void testAdvanced_responseOk() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", TARGET_HOST, group); + //stores future + ChannelFuture future = probingAction.call(); + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + } + + @Test + public void testAdvanced_responseFailure() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", TARGET_HOST, group); + + //stores future + ChannelFuture future = probingAction.call(); + + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } } + From 48f476b9d81843d0c3d908291c3452191f57822c Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 124/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 +++++++++----- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/ProbingSequence.java | 1 - .../monitoring/blackbox/ProbingStep.java | 7 +--- .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 - .../monitoring/blackbox/Tokens/Token.java | 4 +- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../monitoring/blackbox/WebWhoisModule.java | 2 +- .../exceptions/EppClientException.java | 29 ------------- .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++- .../handlers/WebWhoisMessageHandler.java | 22 +++++++++- .../blackbox/messages/HttpRequestMessage.java | 41 +++++++++++++------ .../messages/HttpResponseMessage.java | 26 ++++++++---- .../messages/OutboundMessageType.java | 1 - .../blackbox/TestServers/TestServer.java | 16 +++++++- .../blackbox/TestServers/WebWhoisServer.java | 18 +++++++- 19 files changed, 145 insertions(+), 85 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6387207fea4..2eb90a1d6c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -119,4 +119,3 @@ public String toString() { } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 5bad5abf6bf..80b04a3d0c9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.exceptions.EppClientException; import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; import io.netty.channel.local.LocalAddress; -import java.io.IOException; + import java.util.function.Consumer; import org.joda.time.Duration; @@ -164,7 +162,4 @@ public String toString() { message(), parent); } - } - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 24c666b8d9d..61c83de00fd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -120,4 +120,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dba905c0e49..7200a1877e2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -197,4 +197,4 @@ static SslClientInitializer provideSslClientInitializer(SslPro } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 4afc5d95ba7..0acf223eb9e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; @@ -8,6 +22,11 @@ import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; +/** + * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} + * in case of reuse for redirection + */ public class WebWhoisMessageHandler extends MessageHandler { private HttpRequestMessage request; @@ -15,6 +34,7 @@ public class WebWhoisMessageHandler extends MessageHandler { @Inject public WebWhoisMessageHandler() {} + /** Retains {@link HttpRequestMessage} and calls super write method*/ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { request = (HttpRequestMessage) msg; @@ -23,9 +43,9 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) } + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - FullHttpResponse originalResponse = (FullHttpResponse) msg; InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..b06938d80a1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +31,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,16 +38,19 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + + request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + + return finalRequest; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..283b14440ac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,7 +33,7 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); @@ -26,13 +43,8 @@ public static HttpResponseMessage fromResponse(FullHttpResponse response) { else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); return finalResponse; } - - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 0dd17e9d4a9..2d5df10f8c1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType {} - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 67e2cb7165d..a4474b6b8b5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static com.google.common.truth.Truth.assertThat; @@ -20,7 +34,7 @@ import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { private LocalAddress localAddress; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index ab9997b6c68..06b19ea3607 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -20,10 +34,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - * It will either redirect the client to the correct location if given the + *

It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location + * an unexpected host location

*/ public class WebWhoisServer extends TestServer { From ad39f492d8eda5e156da48872adb4daaa4f2b4ef Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 125/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 --- .../monitoring/blackbox/NewChannelAction.java | 144 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProberModule.java | 80 ++--- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingSequence.java | 130 ++++----- .../monitoring/blackbox/ProbingStep.java | 147 +++++----- .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/Protocol.java | 78 +---- .../monitoring/blackbox/TokenModule.java | 35 --- .../monitoring/blackbox/Tokens/Token.java | 47 --- .../blackbox/Tokens/WebWhoisToken.java | 54 ---- .../monitoring/blackbox/WebWhoisModule.java | 169 ++++++----- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/ActionHandler.java | 102 +++++-- .../blackbox/handlers/MessageHandler.java | 24 -- .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../handlers/WebWhoisMessageHandler.java | 17 +- .../blackbox/messages/HttpRequestMessage.java | 46 ++- .../messages/HttpResponseMessage.java | 14 +- .../messages/OutboundMessageType.java | 11 +- .../monitoring/blackbox/tokens/Token.java | 20 +- .../blackbox/tokens/WebWhoisToken.java | 32 +- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 32 files changed, 704 insertions(+), 987 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 73bd9127852..0daaf16ded4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,99 +14,59 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; import javax.inject.Singleton; +import org.joda.time.Duration; /** - * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} - * - *

Provides

+ * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores + * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. */ @Module public class ProberModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; + /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + private static final Duration DEFAULT_DURATION = new Duration(4000L); + + /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides - @HttpWhoisProtocol - ProbingSequence provideHttpWhoisSequence( - @HttpWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpsWhoisProtocol - ProbingSequence provideHttpsWhoisSequence( - @HttpsWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return httpWhoIsPort; - } - - @Provides - @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return httpsWhoIsPort; + @Singleton + Duration provideDuration() { + return DEFAULT_DURATION; } + /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - ImmutableMap providePortToProtocolMap( - Set protocolSet) { - return Maps.uniqueIndex(protocolSet, Protocol::port); + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - - + /** Root level {@link Component} that provides each {@link ProbingSequence}. */ @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, - TokenModule.class }) public interface ProberComponent { - @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); - - @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); - - ImmutableMap providePortToProtocolMap(); - - @WebWhoisProtocol Token provideWebWhoisToken(); + //Standard WebWhois sequence + @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2eb90a1d6c3..2dbf48256f9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,108 +14,100 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} - * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ - private EventLoopGroup eventGroup; + /**Each {@link ProbingSequence} requires a start token to begin running. */ + private Token startToken; - /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ - private Bootstrap bootstrap; - - public Bootstrap getBootstrap() { - return bootstrap; - } - - public void start(Token token) { - // calls the first step with input token; - firstStep.accept(token); + public void start() { + // calls the first step with startToken; + firstStep.accept(startToken); } /** - * {@link Builder} which takes in {@link ProbingStep}s - * - * @param Same specified {@code C} for overall {@link ProbingSequence} + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. */ - public static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstSequenceStep; - private EventLoopGroup eventLoopGroup; - private Class classType; - - Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public static class Builder { + + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstRepeatedStep; + private Bootstrap bootstrap; + private Token startToken; + + /** + * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. + * + *

Must be called before adding {@link ProbingStep.Builder}s.

+ */ + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } + + /** Adds start token that activate {@link ProbingSequence}. */ + public Builder addToken(Token token) { + startToken = token; return this; } - Builder addStep(ProbingStep step) { - if (currentStep == null) { + /** + * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * built, and pointed to by the previous {@link ProbingStep} added. + */ + public Builder addStep(ProbingStep.Builder stepBuilder) { + assert (bootstrap != null); + ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + + if (currentStep == null) firstStep = step; - } else { + else currentStep.nextStep(step); - } + currentStep = step; return this; } - /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ - Builder makeFirstRepeated() { - firstSequenceStep = currentStep; - return this; - } - /** Set the class to be the same as {@code C} */ - public Builder setClass(Class classType) { - this.classType = classType; + /** We take special note of the first repeated step. */ + public Builder markFirstRepeated() { + firstRepeatedStep = currentStep; return this; } - public ProbingSequence build() { - currentStep.nextStep(firstSequenceStep); + /** + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and + * calls private constructor to create {@link ProbingSequence}. + */ + public ProbingSequence build() { + if (firstRepeatedStep == null) + firstRepeatedStep = firstStep; + + currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); - return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + return new ProbingSequence(this.firstStep, this.startToken); } - } - /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ - private void setParents() { - ProbingStep currentStep = firstStep.parent(this).nextStep(); - - while (currentStep != firstStep) { - currentStep = currentStep.parent(this).nextStep(); - } - } - private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, - Class classType) { + private ProbingSequence(ProbingStep firstStep, Token startToken) { this.firstStep = firstStep; - this.eventGroup = eventLoopGroup; - this.bootstrap = new Bootstrap() - .group(eventGroup) - .channel(classType); - setParents(); - } - - @Override - public String toString() { - return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); - + this.startToken = startToken; } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 80b04a3d0c9..d54acef325a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,152 +14,145 @@ package google.registry.monitoring.blackbox; +import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.local.LocalAddress; - import java.util.function.Consumer; import org.joda.time.Duration; /** - * Represents generator of actions performed at each step in {@link ProbingSequence} - * - * @param See {@code C} in {@link ProbingSequence} + * {@link AutoValue} class that represents generator of actions performed at each step + * in {@link ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies - * these components on each loop iteration with the consumed {@link Token} and from that, - * generates new {@link ProbingAction} to perform<./p> + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. + * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, + * generates a new {@link ProbingAction} to call.

* - *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -public abstract class ProbingStep implements Consumer { +@AutoValue +public abstract class ProbingStep implements Consumer { - public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); - protected static final Duration DEFAULT_DURATION = new Duration(2000L); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - protected LocalAddress address = DEFAULT_ADDRESS; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ private boolean isLastStep = false; - private ProbingStep nextStep; - private ProbingSequence parent; + private ProbingStep nextStep; - protected Duration duration; + abstract Duration duration(); + abstract Protocol protocol(); + abstract OutboundMessageType messageTemplate(); + abstract Bootstrap bootstrap(); - protected final Protocol protocol; - protected final OutboundMessageType message; - protected ProbingStep(Protocol protocol, OutboundMessageType message) { - this.protocol = protocol; - this.message = message; - } + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder setDuration(Duration value); - private OutboundMessageType message() { - return message; - } + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); - Protocol protocol() { - return protocol; + public abstract ProbingStep build(); } + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - ProbingStep parent(ProbingSequence parent) { - this.parent = parent; - return this; - } - - /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ private ProbingAction generateAction(Token token) throws InternalException { - ProbingAction generatedAction; - - OutboundMessageType message = token.modifyMessage(message()); - - //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction - if (protocol().persistentConnection() && token.channel() != null) { - generatedAction = ExistingChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .channel(token.channel()) - .build(); - } else { - generatedAction = NewChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .bootstrap(parent.getBootstrap()) - .address(address) - .build(); - - } - return generatedAction; + OutboundMessageType message = token.modifyMessage(messageTemplate()); + ProbingAction.Builder probingActionBuilder = ProbingAction.builder() + .setDelay(duration()) + .setProtocol(protocol()) + .setOutboundMessage(message) + .setHost(token.getHost()) + .setBootstrap(bootstrap()); + + if (token.channel() != null) + probingActionBuilder.setChannel(token.channel()); + + return probingActionBuilder.build(); } - /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } @Override public void accept(Token token) { - ProbingAction nextAction; + ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - nextAction = generateAction(token); + currentAction = generateAction(token); } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - //If the next step maintains the connection, pass on the channel from this - if (protocol().persistentConnection()) { - token.channel(nextAction.channel()); - } + //call the created action - ChannelFuture future = nextAction.call(); + ChannelFuture future; + + try { + future = currentAction.call(); + + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Performed"); + nextStep.accept(generateNextToken(token)); + return; + } + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - nextStep.accept(generateNextToken(token)); + //If the next step maintains the connection, pass on the channel from this } else { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + token.setChannel(currentAction.channel()); + + nextStep.accept(generateNextToken(token)); + + }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n" + - "and parent sequence: %s", + "OutboundMessage: %s\n", protocol(), - message(), - parent); + messageTemplate().getClass().getName()); } + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 61c83de00fd..b0342c74b7d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,95 +16,43 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; +import io.netty.util.AttributeKey; import javax.inject.Provider; /** - * Protocol Class packages all static variables necessary for a certain type of connection - * Both the host and the path can be changed for the same protocol - * Mainly packages the handlers necessary for the requisite channel pipeline + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. */ @AutoValue public abstract class Protocol { - public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - - /** - * Default names associated with each protocol - */ - final static String EPP_PROTOCOL_NAME = "EPP"; - final static String DNS_PROTOCOL_NAME = "DNS"; - final static String WHOIS_PROTOCOL_NAME = "WHOIS"; - final static String RDAP_PROTOCOL_NAME = "RDAP"; - - private String host; - private String path = ""; - private ProbingAction probingAction; - - /** Setter method for Protocol's host*/ - public Protocol host(String host) { - this.host = host; - return this; - } - - /** Getter method for Protocol's host*/ - public String host() { - return host; - } - - /** Setter method for Protocol's path*/ - public Protocol path(String path) { - this.path = path; - return this; - } - - /** Getter method for Protocol's path*/ - public String path() { - return path; - } - - /** Setter method for Protocol's ProbingAction parent*/ - public Protocol probingAction(ProbingAction probingAction) { - this.probingAction = probingAction; - return this; - } - - /** Getter method for Protocol's path*/ - public ProbingAction probingAction() { - return probingAction; - } - - /** If connection associated with Protocol is persistent, which is only EPP */ - public boolean persistentConnection() { - return name() == EPP_PROTOCOL_NAME; - } + /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - /** Protocol Name */ - public abstract String name(); + abstract String name(); - /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - public abstract ImmutableList> handlerProviders(); + abstract ImmutableList> handlerProviders(); - - public abstract Builder toBuilder(); + /** Boolean that notes if connection associated with Protocol is persistent.*/ + abstract boolean persistentConnection(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } - /** Builder for {@link Protocol}. */ @AutoValue.Builder public abstract static class Builder { - public abstract Builder name(String value); + public abstract Builder setName(String value); + + public abstract Builder setPort(int num); - public abstract Builder port(int num); + public abstract Builder setHandlerProviders(ImmutableList> providers); - public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder setPersistentConnection(boolean value); public abstract Protocol build(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 7200a1877e2..dcc9635beaa 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,62 +17,86 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; -import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandler; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - final static String DOMAIN_SUFFIX = "whois.nic."; + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + private static final String DOMAIN_PREFIX = "whois.nic."; + + /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + private static final int maximumMessageLengthBytes = 512 * 1024; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - - - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - - + /** {@link Provides} standard WebWhois sequence. */ @Provides - @HttpWhoisProtocol - static ProbingStep provideHttpWhoisProbingSequence( - @HttpWhoisProtocol Protocol httpWhoisProtocol) { - return new ProbingStepWeb<>(httpWhoisProtocol); + @WebWhoisProtocol + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, + WebWhoisToken webWhoisToken, + @WebWhoisProtocol Bootstrap bootstrap) { + + return new ProbingSequence.Builder() + .addToken(webWhoisToken) + .setBootstrap(bootstrap) + .addStep(probingStepBuilder) + .build(); } + + /** {@link Provides} only step used in WebWhois sequence. */ @Provides - @HttpsWhoisProtocol - static ProbingStep provideHttpsWhoisProbingStep( - @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { - return new ProbingStepWeb<>(httpsWhoisProtocol); + @WebWhoisProtocol + static ProbingStep.Builder provideWebWhoisStepBuilder( + @HttpWhoisProtocol Protocol httpWhoisProtocol, + HttpRequestMessage messageTemplate, + Duration duration) { + + return ProbingStep.builder() + .setProtocol(httpWhoisProtocol) + .setMessageTemplate(messageTemplate) + .setDuration(duration); } - + /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides @HttpWhoisProtocol @@ -80,28 +104,14 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpProtocolForSet( - @HttpWhoisProtocol int httpWhoisPort, - @HttpWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTP_PROTOCOL_NAME) + .setPort(httpWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } - + /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ @Singleton @Provides @HttpsWhoisProtocol @@ -109,40 +119,28 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpsProtocolForSet( - @HttpsWhoisProtocol int httpsWhoisPort, - @HttpsWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTPS_PROTOCOL_NAME) + .setPort(httpsWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } + /** {@link Provides} the prefix where we probe: "prefix.tld". */ @Provides - @WebWhoisProtocol - String provideHttpWhoisHost() { - return "app"; + @Named("Web-WHOIS-Prefix") + String provideWhoisPrefix() { + return DOMAIN_PREFIX; } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -151,13 +149,14 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -167,33 +166,57 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } + @Provides + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); + } + + @Provides + static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { + return new HttpObjectAggregator(maxContentLength); + } + + /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + @Provides + @HttpsWhoisProtocol + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); + } + /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + @Singleton @Provides @WebWhoisProtocol - static MessageHandler provideMessageHandler() { - return new WebWhoisMessageHandler(); + static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + return new Bootstrap() + .group(eventLoopGroup) + .channel(NioSocketChannel.class); } @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); + @WebWhoisProtocol + int provideMaximumMessageLengthBytes() { + return maximumMessageLengthBytes; } + /** {@link Provides} the list of top level domains to be probed */ + @Singleton @Provides - static HttpObjectAggregator provideHttpObjectAggregator() { - return new HttpObjectAggregator(1048576); + @WebWhoisProtocol + ImmutableList provideTopLevelDomains() { + return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); } @Provides - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index adb833ec629..be3d725c833 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,10 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when - * the action performed failed due to an issue in the connection with the server. + * Base exception class for all instances when the status of the action performed is ERROR. */ -public class ConnectionException extends UndeterminedStateException { +public class ConnectionException extends Exception { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 7898203e92d..e397393b4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,10 +14,11 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; @@ -26,16 +27,18 @@ import io.netty.channel.ChannelPromise; /** - *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} - * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception - * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses - * specify further work to be done for specific kinds of channel pipelines.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed + * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} + * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * + *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -47,28 +50,42 @@ public enum ResponseType {SUCCESS, FAILURE, ERROR} /** Status of response for current {@link ActionHandler} instance */ private static ResponseType status; + /** {@link ChannelPromise} that informs {@link google.registry.monitoring.blackbox.ProbingAction} if response has been received. */ protected ChannelPromise finished; - /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** Returns initialized {@link ChannelPromise} to {@link google.registry.monitoring.blackbox.ProbingAction}.*/ public ChannelFuture getFuture() { return finished; } - /** Initializes new {@link ChannelPromise} */ + /** Initializes the same {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } + /** Initializes the same {@link ChannelPromise} in case current channel is reused (usually for EPP).*/ + public void resetFuture() { + finished = finished.channel().newPromise(); + } + + /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { - //simply marks finished as success + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { + status = ResponseType.SUCCESS; - finished.setSuccess(); + + if (!finished.isSuccess()) { + finished.setSuccess(); + } } - /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ + /** + * Logs the channel and pipeline that caused error, closes channel, then informs + * {@link google.registry.monitoring.blackbox.ProbingAction} listeners of error. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).log(String.format( @@ -76,27 +93,62 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.channel().toString(), ctx.channel().pipeline().toString())); - - if (ResponseException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + if (cause instanceof ResponseException) { + //On ResponseException, we know the response is a failure. As a result, + //we set the status to FAILURE, then inform the MetricsHandler of this status = ResponseType.FAILURE; + + //Since it wasn't a success, we still want to log to see what caused the FAILURE logger.atInfo().log(cause.getMessage()); + + //As always, inform the ProbingStep that we successfully completed this action finished.setSuccess(); - } else if (ServerSideException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + + } else if (cause instanceof ConnectionException) { + //On ConnectionException, we know the response type is an error. As a result, + //we set the status to ERROR, then inform the MetricsHandler of this status = ResponseType.ERROR; + + //Since it wasn't a success, we still log what caused the ERROR logger.atInfo().log(cause.getMessage()); finished.setSuccess(); - } else if (InternalException.class.isInstance(cause)){ + + //As this was an ERROR in the connection, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + } else if (cause instanceof InternalException){ + //For an internal error, metrics should not be collected, so we log what caused this, and + //inform the ProbingStep the Prober had an internal error on this action logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); + + + //As this was an internal error, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } else { - finished.setFailure(cause); + //In the case of any other kind of error, we assume it is some type of connection ERROR, + //so we treat it as such: + + status = ResponseType.ERROR; + + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - //due to failure, close channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + + } + + /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ + @VisibleForTesting + ResponseType getStatus() { + return status; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index ac844ac99df..919006592ea 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -89,8 +90,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); - Protocol protocol = action.protocol(); + Protocol protocol = channel.attr(PROTOCOL_KEY).get(); + String host = channel.attr(REMOTE_ADDRESS_KEY).get(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -103,7 +104,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), action.host(), protocol.port()); + .newHandler(channel.alloc(), host, protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 0acf223eb9e..58c395ad86e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -17,37 +17,36 @@ import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; /** - * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection + * in case of reuse for redirection. */ -public class WebWhoisMessageHandler extends MessageHandler { - - private HttpRequestMessage request; +public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method*/ + /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - request = (HttpRequestMessage) msg; + HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; - InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); + HttpResponseMessage response = new HttpResponseMessage(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b06938d80a1..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,19 +19,30 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); @@ -39,18 +50,29 @@ public HttpRequestMessage setUri(String path) { } /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; - ByteBuf buf = request.content(); + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; - request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + } else { + throw new IllegalArgumentException(); + } + } - return finalRequest; + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 283b14440ac..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -34,17 +34,9 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 2d5df10f8c1..be6c872cc3e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,16 @@ package google.registry.monitoring.blackbox.messages; +import google.registry.monitoring.blackbox.exceptions.InternalException; + /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType {} +public interface OutboundMessageType { + + /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + public OutboundMessageType modifyMessage(String... args) throws InternalException; + + /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + public String name(); +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dab5851e8d8..dd1882b5686 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,18 +14,16 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.ProbingSequence; -import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} - * in a single loop of a {@link ProbingSequence}. + * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} + * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes + * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -33,21 +31,17 @@ */ public abstract class Token { - /** - * {@link Channel} that always starts out as null. Once a persistent connection - * is made (such as EPP), that channel is stored in the token and passed on to - * later steps in the sequence until a new loop begins. - */ + /** {@link Channel} that always starts out as null. */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String host(); + public abstract String getHost(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index bb06ee89db6..2847e5ce0eb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; -import java.util.LinkedList; +import java.util.List; import javax.inject.Inject; import javax.inject.Named; @@ -33,38 +33,42 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final static String PREFIX = "whois.nic."; + private final String prefix; /** {@link ImmutableList} of all top level domains to be probed. */ - private final Iterator topLevelDomainsIterator; + private final ImmutableList topLevelDomains; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private String currentDomain; + private int domainsIndex; @Inject - public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken( + @Named("Web-WHOIS-Prefix") String prefix, + @WebWhoisProtocol ImmutableList topLevelDomains) { - topLevelDomainsIterator = topLevelDomains.iterator(); - currentDomain = topLevelDomainsIterator.next(); + domainsIndex = 0; + this.prefix = prefix; + this.topLevelDomains = topLevelDomains; } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + domainsIndex += 1; + domainsIndex %= topLevelDomains.size(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { - return original.modifyMessage(host()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { + return original.modifyMessage(getHost()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String host() { - return PREFIX + currentDomain; + public String getHost() { + return prefix + topLevelDomains.get(domainsIndex); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Mon, 29 Jul 2019 12:04:58 -0400 Subject: [PATCH 126/337] Minor Style Fixes --- .../monitoring/blackbox/ProbingAction.java | 85 ++++++++++--------- .../monitoring/blackbox/ProbingStep.java | 8 +- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..3f6a962b12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -89,11 +90,47 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** The {@link SocketAddress} instance that specifies remote address of connection */ + @Nullable public abstract SocketAddress address(); /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ public abstract Optional bootstrap(); + + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> actionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** * The method that performs the work of the actual action. * @@ -130,41 +167,13 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } @@ -224,7 +233,7 @@ public abstract static class Builder { abstract Channel channel(); - abstract Optional address(); + abstract SocketAddress address(); abstract Optional bootstrap(); @@ -233,7 +242,7 @@ public abstract static class Builder { abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) + if (address() == null) //If no address has been supplied, we set it based on the host and port setAddress(new InetSocketAddress(host(), protocol().port())); @@ -259,7 +268,7 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap().get().connect(address()); setChannel(connectionFuture.channel()); setConnectionFuture(connectionFuture); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index d54acef325a..47c89c72c11 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -21,7 +21,9 @@ import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import java.net.SocketAddress; import java.util.function.Consumer; +import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -48,6 +50,7 @@ public abstract class ProbingStep implements Consumer { abstract Protocol protocol(); abstract OutboundMessageType messageTemplate(); abstract Bootstrap bootstrap(); + @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -60,6 +63,8 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); + public abstract Builder setAddress(SocketAddress address); + public abstract ProbingStep build(); } @@ -87,7 +92,8 @@ private ProbingAction generateAction(Token token) throws InternalException { .setProtocol(protocol()) .setOutboundMessage(message) .setHost(token.getHost()) - .setBootstrap(bootstrap()); + .setBootstrap(bootstrap()) + .setAddress(address()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); From ed5ed7930b6cb3907bbc3935aecea50d0aa91732 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:05:59 -0400 Subject: [PATCH 127/337] Updated build.gradle file --- prober/build.gradle | 3 - .../blackbox/ProbingSequenceStepTest.java | 219 ------------------ .../blackbox/ProbingSequenceTest.java | 96 -------- .../monitoring/blackbox/ProbingStepTest.java | 196 ++++++++-------- 4 files changed, 102 insertions(+), 412 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java diff --git a/prober/build.gradle b/prober/build.gradle index e48eacb8bf9..26d44c0a465 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,8 +16,6 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - - dependencies { def deps = rootProject.dependencyMap @@ -46,7 +44,6 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java deleted file mode 100644 index 7a713017072..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.TestUtils.TestStep; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.handlers.ConversionHandler; -import google.registry.monitoring.blackbox.handlers.NettyRule; -import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; -import org.junit.Rule; -import org.junit.Test; - -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { - - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ - private ProbingSequence testSequence; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); - dummyStep = new DummyStep(testProtocol, eventLoopGroup); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(false) - .build(); - } - - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(true) - .build(); - } - - /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ - private void setupSequence() { - testSequence = new ProbingSequence.Builder() - .eventLoopGroup(eventLoopGroup) - .setClass(LocalChannel.class) - .addStep(firstStep) - .makeFirstRepeated() - .addStep(dummyStep) - .build(); - } - - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.nextStep()).isNull(); - - //we expect that this exception be thrown - assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); - - } - - @Test - public void testWithSequence_NewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupSequence(); - setupNewChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupSequence(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 5c4452df7b3..2b0559514a2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,101 +1,5 @@ -// Copyright 2019 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.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doCallRealMethod; - -import google.registry.monitoring.blackbox.tokens.Token; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) public class ProbingSequenceTest { - - private ProbingStep setupMock() { - ProbingStep mock = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(mock).nextStep(); - return mock; - } - - private static class Wrapper { - - T data; - - public Wrapper(T data) { - this.data = data; - } - } - - @Test - public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(firstStep) - .addStep(secondStep) - .addStep(thirdStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(thirdStep); - assertThat(thirdStep.nextStep()).isEqualTo(firstStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - - @Test - public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(thirdStep) - .addStep(secondStep) - .markFirstRepeated() - .addStep(firstStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(firstStep); - assertThat(thirdStep.nextStep()).isEqualTo(secondStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 1f09dd13553..090753014e4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,59 +11,57 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.TestUtils.dummyStep; +import static google.registry.monitoring.blackbox.TestUtils.testStep; +import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; -import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; -import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingStepTest { +public class ProbingSequenceStepTest { /** Basic Constants necessary for tests */ - private final static String ADDRESS_NAME = "TEST_ADDRESS"; - private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final static int PROTOCOL_PORT = 0; - private final static String TEST_MESSAGE = "TEST_MESSAGE"; - private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -74,106 +72,117 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** - * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} - * is called, it just marks the supplied future as succeeded, returning the requisite token. - */ - private ProbingStep dummyStep() { - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(dummyStep).nextStep(); - return dummyStep; + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); } + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } - @Test - public void testNewChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); + dummyStep = dummyStep(eventLoopGroup); - // Sets up Protocol for when we create a new channel. - Protocol testProtocol = Protocol.builder() + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); + } - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) .build(); + } - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); + //there should be no next step + assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); - //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(address); + } + + @Test + public void testNewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //checks that we have appropriately sent the write message to server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - verify(dummyStep, times(1)).accept(any(Token.class)); + assertThat(future.get()).isEqualTo(testToken); + } - @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - - // Sets up Protocol for when a channel already exists. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) - .build(); - - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) - .build(); - - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); - - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - - //Assures that the channel has a succeeded connectionFuture. - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, ""); + //setup + setupExistingProtocol(); + setupSteps(); + setupChannel(); + setupExistingChannelToken(); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -182,21 +191,20 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); - Object msg = channel.readOutbound(); - - while (msg == null) { - msg = channel.readOutbound(); - } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked - // as a success - verify(dummyStep, times(1)).accept(any(Token.class)); + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); } } From a1dd385c5f9ce6c8958fb09bca99c6551fcea431 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 128/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From 36c9ad50a628cd7dbe3eea561c6ee7fdc84726c0 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:54:13 -0400 Subject: [PATCH 129/337] Updated WebWhois tests. --- .../blackbox/ProbingActionTest.java | 56 +++--- .../blackbox/ProbingSequenceTest.java | 183 ++++++++++++++++++ .../monitoring/blackbox/ProbingStepTest.java | 3 +- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 93 +++++++-- .../monitoring/blackbox/TokenTest.java | 13 +- .../blackbox/handlers/ConversionHandler.java | 2 +- .../blackbox/handlers/NettyRule.java | 12 +- .../handlers/SslClientInitializerTest.java | 46 ++--- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 159 ++++++++------- 11 files changed, 422 insertions(+), 157 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index cbcf2fc82b0..162044c2036 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -83,31 +84,31 @@ public class ProbingActionTest { /** Sets up a {@link Protocol} corresponding to when a new connection is created */ private void setupNewChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(false) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) .build(); } /** Sets up a {@link Protocol} corresponding to when a new connection exists */ private void setupExistingChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(true) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(true) .build(); } - /** Sets up a {@link NewChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ private void setupNewChannelAction() { - newChannelAction = NewChannelAction.builder() - .bootstrap(bootstrap) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") - .address(address) + newChannelAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") + .setAddress(address) .build(); } @@ -115,25 +116,25 @@ private void setupChannel() { channel = new EmbeddedChannel(); } - /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ExistingChannelAction.builder() - .channel(channel) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") + existingChannelAction = ProbingAction.builder() + .setChannel(channel) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") .build(); } @Test - public void testBehavior_existingChannel() { + public void testBehavior_existingChannel() throws InternalException { //setup setupChannel(); setupExistingChannelProtocol(); - setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); + setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -147,6 +148,7 @@ public void testBehavior_existingChannel() { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -156,9 +158,9 @@ public void testBehavior_existingChannel() { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - setupNewChannelAction(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + setupNewChannelAction(); ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2b0559514a2..681a5346d55 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,5 +1,188 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; + +import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; +import java.net.SocketAddress; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) public class ProbingSequenceTest { + private final static String TEST_HOST = "TEST_HOST"; + + + private Bootstrap dummyBootstrap = new Bootstrap(); + private Token testToken = new ProbingSequenceTestToken(); + + /** + * Custom {@link ProbingStep} subclass that acts as a mock + * step, so we can test how well {@link ProbingSequence} builds + * a linked list of {@link ProbingStep}s from their {@link Builder}s. + */ + private static class TestStep extends ProbingStep { + private Bootstrap bootstrap; + private String marker; + + /** We implement all abstract methods to simply return null, as we have no use for them here. */ + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + SocketAddress address() { + return null; + } + + /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + /** + * Builder for {@link TestStep}, that extends {@link ProbingStep.Builder} so that these can be + * input into the {@link ProbingSequence.Builder}. + */ + public static class Builder extends ProbingStep.Builder { + /** We test to see if we accurately add the right bootstrap to all {@link ProbingStep}s/ */ + private Bootstrap bootstrap; + + /** We also mark each step in order to ensure that when running, they are arranged in the right order. */ + private String marker; + + @Override + public ProbingStep.Builder setDuration(Duration value) { + return this; + } + + @Override + public ProbingStep.Builder setProtocol(Protocol value) { + return this; + } + + @Override + public ProbingStep.Builder setMessageTemplate(OutboundMessageType value) { + return null; + } + + @Override + public ProbingStep.Builder setAddress(SocketAddress address) { + return null; + } + + @Override + public ProbingStep.Builder setBootstrap(Bootstrap value) { + bootstrap = value; + return this; + } + + public ProbingStep.Builder addMarker(String value) { + marker = value; + return this; + } + + @Override + public ProbingStep build() { + return new TestStep(bootstrap, marker); + } + } + private TestStep(Bootstrap bootstrap, String marker) { + this.bootstrap = bootstrap; + this.marker = marker; + } + + /** + * On a call to accept, we modify the token to reflect what the current step is, so we can get + * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated + * in order. + */ + @Override + public void accept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + if (!isLastStep) { + nextStep().accept(token); + } else { + ((TestStep)nextStep()).specialAccept(token); + } + } + + /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ + public void specialAccept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + return; + } + } + + @Test + public void testSequenceBasicConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("firstsecondthirdfirst"); + } + + @Test + public void testSequenceAdvancedConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(thirdStepBuilder) + .addStep(secondStepBuilder) + .markFirstRepeated() + .addStep(firstStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("thirdsecondfirstsecond"); + } + @Test + public void testSequenceConstruction_Failure() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + assertThrows(AssertionError.class, () -> { + ProbingSequence sequence = new ProbingSequence.Builder() + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .setBootstrap(dummyBootstrap) + .build(); + }); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 090753014e4..ee38e7cdf74 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -21,7 +21,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; @@ -47,7 +46,7 @@ import org.junit.Test; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { +public class ProbingStepTest { /** Basic Constants necessary for tests */ private final String ADDRESS_NAME = "TEST_ADDRESS"; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 06b19ea3607..337d755e971 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -93,11 +93,11 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 8d1722c9625..161304c1f04 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,9 +17,11 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -37,6 +39,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; +import java.net.Socket; +import java.net.SocketAddress; +import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -141,26 +146,67 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } + + @Override + public OutboundMessageType modifyMessage(String... args) throws InternalException { + message = args[0]; + return this; + } + + @Override + public String name() { + return "Test Message of: " + this.toString(); + } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static class TestStep extends ProbingStep { + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .setAddress(address) + .build(); - public TestStep(Protocol protocol, String testMessage, LocalAddress address) { - super(protocol, new DuplexMessageTest(testMessage)); - this.address = address; - this.duration = Duration.ZERO; - } + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { - super(protocol, new DuplexMessageTest()); - future = new DefaultPromise(eventLoopGroup.next()) {}; - duration = Duration.ZERO; + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; + } + + @Nullable + @Override + SocketAddress address() { + return null; } @Override @@ -170,11 +216,16 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } + + @Override + public String toString() { + return "Dummy Step"; + } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - private String host; + protected String host; protected TestToken(String host) { this.host = host; @@ -221,6 +272,22 @@ public Channel channel() { } } + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..67963805733 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,10 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; @@ -34,20 +35,20 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..a8506a996a9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -37,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b6b5e8fbe0c..b38c1911940 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; @@ -89,7 +90,8 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - ProbingAction probingAction, + Protocol protocol, + String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -109,7 +111,9 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROBING_ACTION_KEY, probingAction); + .attr(PROTOCOL_KEY, protocol) + .attr(REMOTE_ADDRESS_KEY, host); + channel = b.connect(localAddress).syncUninterruptibly().channel(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 469c62a8f75..83c8e132f07 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,17 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ExistingChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; @@ -45,7 +46,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; -import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,8 +67,6 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); - /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -93,15 +91,12 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .persistentConnection(false) - .build(); - - private ProbingAction probingAction; + private final static Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -113,23 +108,13 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } - private void setupProbingAction(Channel channel) { - probingAction = ExistingChannelAction.builder() - .delay(Duration.ZERO) - .host(SSL_HOST) - .channel(channel) - .outboundMessage(DEFAULT_MESSAGE) - .protocol(PROTOCOL) - .build(); - } - @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - setupProbingAction(channel); - channel.attr(PROBING_ACTION_KEY).set(probingAction); + channel.attr(PROTOCOL_KEY).set(PROTOCOL); + channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -160,8 +145,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -189,8 +173,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -219,8 +202,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 518bb9ba686..e170fad8b8c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox.handlers; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index d8a672758da..72d5d5078df 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,21 +15,21 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; @@ -65,6 +65,14 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); + private static final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of()) + .setName("test_protocol") + .setPersistentConnection(false) + .setPort(HTTPS_PORT) + .build(); + private LocalAddress address; private EmbeddedChannel channel; @@ -75,30 +83,38 @@ public class WebWhoisActionHandlerTest { private void generateLocalAddress() { address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); } + /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port) { + private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of(actionHandlerProvider)) - .persistentConnection(false) + .setName(name) + .setPort(port) + .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) + .setPersistentConnection(persistentConnection) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); + private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { + actionHandler = new WebWhoisActionHandler( + bootstrap, + STANDARD_PROTOCOL, + STANDARD_PROTOCOL, + messageTemplate, + 80, + 443 + ); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); setupProbingActionBasic( protocol, outboundMessage, makeBootstrap(new NioEventLoopGroup(1))); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROBING_ACTION_KEY).set(probingAction); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -108,24 +124,25 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { } /**Sets up probingAction for when testing redirection */ private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(TARGET_HOST) - .address(DEFAULT_ADDRESS) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(TARGET_HOST) + .setAddress(DEFAULT_ADDRESS) + .setChannel(channel) .build(); } private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(host) - .address(address) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(host) + .setAddress(address) .build(); } @@ -136,10 +153,13 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, true); generateLocalAddress(); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + + setupChannel(initialProtocol, msg); //stores future @@ -151,7 +171,7 @@ public void testBasic_responseOk() throws Exception { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -161,15 +181,16 @@ public void testBasic_responseOk() throws Exception { //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseBad", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseBad", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -181,8 +202,7 @@ public void testBasic_responseFailure() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage - .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -194,14 +214,15 @@ public void testBasic_responseFailure() { assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseError() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseError", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseError", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -213,7 +234,7 @@ public void testBasic_responseError() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -224,27 +245,30 @@ public void testBasic_responseError() { assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_redirectCloseChannel() { //setup - HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", 0); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", 0, true); generateLocalAddress(); - setupChannel(initialProtocol, outboundMessage); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(outboundMessage); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -260,12 +284,15 @@ public void testBasic_redirectCloseChannel() { @Test public void testBasic_redirectHost() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); generateLocalAddress(); setupChannel(initialProtocol, msg); - HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); //store future @@ -275,27 +302,24 @@ public void testBasic_redirectHost() { channel.writeInbound(originalResponse); - ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - //gets changed protocol - Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); - assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); } @Test - public void testAdvanced_responseOk() { + public void testAdvanced_responseOk() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); //stores future ChannelFuture future = probingAction.call(); @@ -305,15 +329,16 @@ public void testAdvanced_responseOk() { } @Test - public void testAdvanced_responseFailure() { + public void testAdvanced_responseFailure() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); //stores future ChannelFuture future = probingAction.call(); From 67350eda6bcf6784a1a453fbbddc1fd471e9d28b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 130/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- prober/.gitignore | 2 +- .../registry/monitoring/blackbox/Prober.java | 9 +- .../monitoring/blackbox/ProberModule.java | 15 ++- .../monitoring/blackbox/ProbingAction.java | 96 +++++++-------- .../monitoring/blackbox/ProbingSequence.java | 24 +--- .../monitoring/blackbox/ProbingStep.java | 55 ++++++--- .../monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 49 ++++---- .../exceptions/ConnectionException.java | 5 +- .../blackbox/exceptions/FailureException.java | 15 ++- .../exceptions/InternalException.java | 30 ----- .../exceptions/ResponseException.java | 29 ----- .../blackbox/handlers/ActionHandler.java | 94 +++------------ .../handlers/WebWhoisActionHandler.java | 51 ++++---- .../blackbox/messages/HttpRequestMessage.java | 4 +- .../messages/HttpResponseMessage.java | 6 +- .../messages/OutboundMessageType.java | 7 +- .../monitoring/blackbox/tokens/Token.java | 20 +-- .../blackbox/tokens/WebWhoisToken.java | 32 +++-- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../blackbox/ProbingActionTest.java | 9 +- .../blackbox/ProbingSequenceTest.java | 114 +++--------------- .../monitoring/blackbox/ProbingStepTest.java | 4 +- .../monitoring/blackbox/TestUtils.java | 21 +--- .../monitoring/blackbox/TokenTest.java | 8 +- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 106 +++++----------- 31 files changed, 291 insertions(+), 526 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/.gitignore b/prober/.gitignore index c86568e7672..77b1e2de2de 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..307afd34d81 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +29,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 0daaf16ded4..1db97d1b581 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,14 +14,18 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.Set; import javax.inject.Singleton; import org.joda.time.Duration; @@ -33,7 +37,7 @@ public class ProberModule { /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = new Duration(4000L); + private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @@ -42,6 +46,12 @@ EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + @Provides + @Singleton + Class provideChannelClass() { + return NioSocketChannel.class; + } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides @Singleton @@ -51,6 +61,7 @@ Duration provideDuration() { /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides + @Singleton static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; @@ -66,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); + Set provideAllSequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 3f6a962b12d..67494dd5f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,25 +14,29 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -65,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -80,31 +87,18 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - @Nullable - public abstract SocketAddress address(); - - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { // Write appropriate outboundMessage to pipeline ChannelFuture channelFuture = actionHandler.getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> actionHandler.resetFuture(), - //inform ProbingStep of the status of our action future -> { if (future.isSuccess()) @@ -141,7 +135,7 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -154,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -180,19 +174,24 @@ public ChannelFuture performAction() throws InternalException { /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -210,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -221,40 +226,30 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract SocketAddress address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (address() == null) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + System.out.println("test"); + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -268,14 +263,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -293,7 +285,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2dbf48256f9..91c4165c068 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -49,32 +49,18 @@ public static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; private ProbingStep firstRepeatedStep; - private Bootstrap bootstrap; - private Token startToken; - /** - * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. - * - *

Must be called before adding {@link ProbingStep.Builder}s.

- */ - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } + private Token startToken; - /** Adds start token that activate {@link ProbingSequence}. */ - public Builder addToken(Token token) { - startToken = token; - return this; + public Builder(Token startToken) { + this.startToken = startToken; } /** - * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, * built, and pointed to by the previous {@link ProbingStep} added. */ - public Builder addStep(ProbingStep.Builder stepBuilder) { - assert (bootstrap != null); - ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + public Builder addStep(ProbingStep step) { if (currentStep == null) firstStep = step; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 47c89c72c11..ca980100067 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import java.net.SocketAddress; import java.util.function.Consumer; -import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -39,18 +37,23 @@ @AutoValue public abstract class ProbingStep implements Consumer { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ - private boolean isLastStep = false; + protected boolean isLastStep = false; private ProbingStep nextStep; + /** Time delay duration between actions. */ abstract Duration duration(); + + /** {@link Protocol} type for this step. */ abstract Protocol protocol(); + + /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ abstract OutboundMessageType messageTemplate(); + + /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ abstract Bootstrap bootstrap(); - @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -63,8 +66,6 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); - public abstract Builder setAddress(SocketAddress address); - public abstract ProbingStep build(); } @@ -85,18 +86,18 @@ ProbingStep nextStep() { } /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws InternalException { + private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) .setProtocol(protocol()) .setOutboundMessage(message) - .setHost(token.getHost()) - .setBootstrap(bootstrap()) - .setAddress(address()); + .setHost(token.host()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); + else + probingActionBuilder.setBootstrap(bootstrap()); return probingActionBuilder.build(); } @@ -107,44 +108,58 @@ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } + /** + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. + * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

+ */ @Override public void accept(Token token) { ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - //call the created action ChannelFuture future; - try { + //call the generated action future = currentAction.call(); - - } catch(InternalException e) { + } catch(UndeterminedStateException e) { + //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); + + //Move on to next step in ProbingSequence nextStep.accept(generateNextToken(token)); return; } - //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - //If the next step maintains the connection, pass on the channel from this + } else { + //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index b0342c74b7d..92470ef62c8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -29,7 +29,7 @@ public abstract class Protocol { /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - abstract String name(); + public abstract String name(); public abstract int port(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dcc9635beaa..c5e41fea38b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,6 +18,7 @@ import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,6 +27,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; @@ -44,11 +46,10 @@ @Module public class WebWhoisModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - private static final String DOMAIN_PREFIX = "whois.nic."; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; + private static final String HTTP_PROTOCOL_NAME = "http"; + private static final String HTTPS_PROTOCOL_NAME = "https"; /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; @@ -68,16 +69,14 @@ public class WebWhoisModule { /** {@link Provides} standard WebWhois sequence. */ @Provides - @WebWhoisProtocol + @Singleton + @IntoSet ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, - WebWhoisToken webWhoisToken, - @WebWhoisProtocol Bootstrap bootstrap) { + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { - return new ProbingSequence.Builder() - .addToken(webWhoisToken) - .setBootstrap(bootstrap) - .addStep(probingStepBuilder) + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) .build(); } @@ -85,15 +84,18 @@ ProbingSequence provideWebWhoisSequence( /** {@link Provides} only step used in WebWhois sequence. */ @Provides @WebWhoisProtocol - static ProbingStep.Builder provideWebWhoisStepBuilder( + static ProbingStep provideWebWhoisStep( @HttpWhoisProtocol Protocol httpWhoisProtocol, + @WebWhoisProtocol Bootstrap bootstrap, HttpRequestMessage messageTemplate, Duration duration) { return ProbingStep.builder() .setProtocol(httpWhoisProtocol) + .setBootstrap(bootstrap) .setMessageTemplate(messageTemplate) - .setDuration(duration); + .setDuration(duration) + .build(); } /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @@ -126,13 +128,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** {@link Provides} the prefix where we probe: "prefix.tld". */ - @Provides - @Named("Web-WHOIS-Prefix") - String provideWhoisPrefix() { - return DOMAIN_PREFIX; - } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @@ -187,10 +182,12 @@ static SslClientInitializer provideSslClientInitializer(SslPro @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + static Bootstrap provideBootstrap( + EventLoopGroup eventLoopGroup, + Class channelClass){ return new Bootstrap() .group(eventLoopGroup) - .channel(NioSocketChannel.class); + .channel(channelClass); } @Provides @@ -210,13 +207,13 @@ ImmutableList provideTopLevelDomains() { @Provides @HttpWhoisProtocol int provideHttpWhoisPort() { - return httpWhoIsPort; + return HTTP_WHOIS_PORT; } @Provides @HttpsWhoisProtocol int provideHttpsWhoisPort() { - return httpsWhoIsPort; + return HTTPS_WHOIS_PORT; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index be3d725c833..adb833ec629 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,9 +15,10 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is ERROR. + * Subclass of {@link UndeterminedStateException} that represents all instances when + * the action performed failed due to an issue in the connection with the server. */ -public class ConnectionException extends Exception { +public class ConnectionException extends UndeterminedStateException { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 9f716bb2589..36687e7ac82 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,5 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.exceptions; +/** + * Base exception class for all instances when the status of the action performed is FAILURE. + */ +public class FailureException extends Exception { + + public FailureException(String msg) { + super(msg); + } + + public FailureException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index e397393b4e9..0c9e93cc6dd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,13 +14,11 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -33,7 +31,7 @@ * messages that implement the {@link InboundMessageType} interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

@@ -44,111 +42,59 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); - - } else if (cause instanceof InternalException){ - //For an internal error, metrics should not be collected, so we log what caused this, and - //inform the ProbingStep the Prober had an internal error on this action - logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - - //As this was an internal error, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } else { - //In the case of any other kind of error, we assume it is some type of connection ERROR, - //so we treat it as such: + //On UndeterminedStateException, we know the response type is an error. - status = ResponseType.ERROR; - - logger.atInfo().log(cause.getMessage()); - finished.setSuccess(); + //Since it wasn't a success, we still log what caused the ERROR + logger.atWarning().log(cause.getMessage()); + finished.setFailure(cause); + //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } - - /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ - @VisibleForTesting - ResponseType getStatus() { - return status; - } -} - +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 69d5b7f1603..1ec4e314813 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -22,13 +22,12 @@ import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -62,27 +61,17 @@ public class WebWhoisActionHandler extends ActionHandler { /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ private final HttpRequestMessage requestMessage; - /** Default port for http. */ - private int httpPort; - - /** default port for https. */ - private int httpsPort; - @Inject public WebWhoisActionHandler( @WebWhoisProtocol Bootstrap bootstrap, @HttpWhoisProtocol Protocol httpWhoisProtocol, @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage, - @HttpWhoisProtocol int httpPort, - @HttpsWhoisProtocol int httpsPort) { + HttpRequestMessage requestMessage) { this.bootstrap = bootstrap; this.httpWhoisProtocol = httpWhoisProtocol; this.httpsWhoisProtocol = httpsWhoisProtocol; this.requestMessage = requestMessage; - this.httpPort = httpPort; - this.httpsPort = httpsPort; } @@ -93,7 +82,7 @@ public WebWhoisActionHandler( */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -112,7 +101,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -123,12 +112,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; - if (newPort == httpPort) { + if (url.getProtocol().equals(httpWhoisProtocol.name())) { newProtocol = httpWhoisProtocol; - } else if (newPort == httpsPort) { + } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -143,34 +132,38 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) .setHost(newHost) .build(); - //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); - //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..b4c01d06a8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,12 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..f1b2d6ac6a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -25,11 +25,7 @@ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { - super(version, status); - } - - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index be6c872cc3e..6e3da3f69d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,7 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline @@ -22,8 +22,9 @@ public interface OutboundMessageType { /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - public OutboundMessageType modifyMessage(String... args) throws InternalException; + OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - public String name(); + @Override + String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dd1882b5686..dab5851e8d8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,16 +14,18 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.ProbingSequence; +import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} - * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} + * in a single loop of a {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * in a {@link ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -31,17 +33,21 @@ */ public abstract class Token { - /** {@link Channel} that always starts out as null. */ + /** + * {@link Channel} that always starts out as null. Once a persistent connection + * is made (such as EPP), that channel is stored in the token and passed on to + * later steps in the sequence until a new loop begins. + */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String getHost(); + public abstract String host(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 2847e5ce0eb..bb06ee89db6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import javax.inject.Inject; import javax.inject.Named; @@ -33,42 +33,38 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final String prefix; + private final static String PREFIX = "whois.nic."; /** {@link ImmutableList} of all top level domains to be probed. */ - private final ImmutableList topLevelDomains; + private final Iterator topLevelDomainsIterator; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private int domainsIndex; + private String currentDomain; @Inject - public WebWhoisToken( - @Named("Web-WHOIS-Prefix") String prefix, - @WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { - domainsIndex = 0; - this.prefix = prefix; - this.topLevelDomains = topLevelDomains; + topLevelDomainsIterator = topLevelDomains.iterator(); + currentDomain = topLevelDomainsIterator.next(); } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - domainsIndex += 1; - domainsIndex %= topLevelDomains.size(); + currentDomain = topLevelDomainsIterator.next(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { - return original.modifyMessage(getHost()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + return original.modifyMessage(host()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String getHost() { - return prefix + topLevelDomains.get(domainsIndex); + public String host() { + return PREFIX + currentDomain; } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( { - ProbingSequence sequence = new ProbingSequence.Builder() - .addStep(firstStepBuilder) - .addStep(secondStepBuilder) - .addStep(thirdStepBuilder) - .addToken(testToken) - .setBootstrap(dummyBootstrap) - .build(); - }); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index ee38e7cdf74..7bba9d66782 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.TestUtils.dummyStep; import static google.registry.monitoring.blackbox.TestUtils.testStep; import static google.registry.testing.JUnitBackports.assertThrows; @@ -90,7 +91,7 @@ public class ProbingStepTest { /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ private void setupNewChannelToken() { - testToken = new NewChannelToken(""); + testToken = new NewChannelToken(ADDRESS_NAME); } /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ @@ -101,6 +102,7 @@ private void setupExistingChannelToken() { /** Sets up an embedded channel to contain the two handlers we created already */ private void setupChannel() { channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 161304c1f04..68bdd0bcef0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,7 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,8 +26,6 @@ import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpMessage; @@ -39,7 +37,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; -import java.net.Socket; import java.net.SocketAddress; import javax.annotation.Nullable; import javax.inject.Provider; @@ -148,15 +145,10 @@ public String toString() { } @Override - public OutboundMessageType modifyMessage(String... args) throws InternalException { + public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { message = args[0]; return this; } - - @Override - public String name() { - return "Test Message of: " + this.toString(); - } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ @@ -166,7 +158,6 @@ public static ProbingStep testStep(Protocol protocol, String testMessage, Bootst .setDuration(Duration.ZERO) .setMessageTemplate(new DuplexMessageTest(testMessage)) .setBootstrap(bootstrap) - .setAddress(address) .build(); } @@ -203,12 +194,6 @@ Bootstrap bootstrap() { return null; } - @Nullable - @Override - SocketAddress address() { - return null; - } - @Override public void accept(Token token) { future.setSuccess(token); @@ -241,7 +226,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String getHost() { + public String host() { return host; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index 67963805733..295bb809a13 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -17,12 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -37,7 +35,7 @@ public class TokenTest { private static String TEST_STARTER = "starter"; private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { @@ -49,7 +47,7 @@ public void testWebToken_MessageModificationSuccess() { try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index e170fad8b8c..3ecbdcc0d06 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -29,7 +29,7 @@ public class TestActionHandler extends ActionHandler { @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 72d5d5078df..2483bd65b1f 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,21 +15,23 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; @@ -64,11 +66,9 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); private static final Protocol STANDARD_PROTOCOL = Protocol.builder() .setHandlerProviders(ImmutableList.of()) - .setName("test_protocol") + .setName("http") .setPersistentConnection(false) .setPort(HTTPS_PORT) .build(); @@ -80,8 +80,10 @@ public class WebWhoisActionHandlerTest { private ProbingAction probingAction; private Provider actionHandlerProvider; - private void generateLocalAddress() { - address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + private String generateLocalAddress(String addressString) { + String modifiedAddress = addressString + System.currentTimeMillis(); + address = new LocalAddress(modifiedAddress); + return modifiedAddress; } /** Creates default protocol with empty list of handlers and specified other inputs */ @@ -100,9 +102,7 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT bootstrap, STANDARD_PROTOCOL, STANDARD_PROTOCOL, - messageTemplate, - 80, - 443 + messageTemplate ); actionHandlerProvider = new TestProvider<>(actionHandler); } @@ -111,10 +111,8 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - setupProbingActionBasic( - protocol, - outboundMessage, - makeBootstrap(new NioEventLoopGroup(1))); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -123,26 +121,23 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } /**Sets up probingAction for when testing redirection */ - private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) .setHost(TARGET_HOST) - .setAddress(DEFAULT_ADDRESS) .setChannel(channel) .build(); } - private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) .setBootstrap(bootstrap) - .setHost(host) - .setAddress(address) + .setHost(addressString) .build(); } @@ -157,8 +152,6 @@ public void testBasic_responseOk() throws Exception { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseOk", 0, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); @@ -185,13 +178,12 @@ public void testBasic_responseOk() throws Exception { } @Test - public void testBasic_responseFailure() { + public void testBasic_responseFailure_badRequest() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseBad", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -211,19 +203,18 @@ public void testBasic_responseFailure() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testBasic_responseError() { + public void testBasic_responseFailure_badURL() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseError", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -243,9 +234,9 @@ public void testBasic_responseError() { //assesses that listener is triggered, and event is success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException); } @Test @@ -257,7 +248,6 @@ public void testBasic_redirectCloseChannel() { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("redirectHttp", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -282,44 +272,15 @@ public void testBasic_redirectCloseChannel() { } @Test - public void testBasic_redirectHost() { + public void testAdvanced_responseOk() throws UndeterminedStateException { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); - HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); - - - //store future - ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); - - - channel.writeInbound(originalResponse); - - Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - } - - @Test - public void testAdvanced_responseOk() throws InternalException { - //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); @@ -329,22 +290,21 @@ public void testAdvanced_responseOk() throws InternalException { } @Test - public void testAdvanced_responseFailure() throws InternalException { + public void testAdvanced_responseFailure() throws UndeterminedStateException { //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); + String host = generateLocalAddress(TARGET_HOST); HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(bootstrap, msg); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + assertThrows(FailureException.class, future::syncUninterruptibly); } } From 48e4d53d840ed4727da3a31e7f1b61487138c5fb Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:48:33 -0400 Subject: [PATCH 131/337] SpotlessApply run to fix style issues --- prober/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index 77b1e2de2de..c86568e7672 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From 3f5dfc0595149d38ffb97b2a1e51634ef485758b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:28:40 -0400 Subject: [PATCH 132/337] Added license header and newline where appropriate. --- prober/build.gradle | 1 + .../monitoring/blackbox/ProbingAction.java | 1 - .../blackbox/handlers/ActionHandler.java | 2 +- .../monitoring/blackbox/ProbingSequenceTest.java | 14 ++++++++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 26d44c0a465..70b8e2a6b8b 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -35,6 +35,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] + compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 67494dd5f78..a8740e21c20 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -240,7 +240,6 @@ public ProbingAction build() { InetAddress hostAddress = InetAddress.getByName(host()); address = new InetSocketAddress(hostAddress, protocol().port()); } catch (UnknownHostException e) { - System.out.println("test"); address = new LocalAddress(host()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 0c9e93cc6dd..8a108b81006 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -97,4 +97,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } -} \ No newline at end of file +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2a8d5ebe233..8d9e45c6a66 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; From 172cb190d9da477aacc72299f763202edd564427 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 133/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/ProbingStepTest.java | 1 - .../blackbox/TestServers/WebWhoisServer.java | 3 +- .../monitoring/blackbox/TestUtils.java | 35 +------------------ .../blackbox/handlers/ConversionHandler.java | 5 ++- .../blackbox/handlers/NettyRule.java | 4 ++- 5 files changed, 10 insertions(+), 38 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 7bba9d66782..73b104ae5dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -174,7 +174,6 @@ public void testNewChannel() throws Exception { //checks that when the future is successful, we pass down the requisite token assertThat(future.get()).isEqualTo(testToken); - } @Test diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 337d755e971..e7f125bb906 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; @@ -80,7 +81,7 @@ static class RedirectHandler extends ChannelDuplexHandler { /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 68bdd0bcef0..cc8e1512fe9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; @@ -28,17 +27,13 @@ import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpMethod;; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; import java.net.SocketAddress; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -272,33 +267,5 @@ public void addToHost(String suffix) { } } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index a8506a996a9..196141bb875 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b38c1911940..1d14cf131e6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -26,6 +26,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.ProbingActionTest; +import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; @@ -54,7 +56,7 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { From 6b1ab3d1c49f5e47c94dbec8efd080fb9383a5f4 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 5 Aug 2019 16:16:36 -0400 Subject: [PATCH 134/337] Refactored ProbingAction to minimize number of unnecessary methods --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 4 +- .../monitoring/blackbox/ProbingAction.java | 160 ++++++++---------- .../monitoring/blackbox/ProbingStep.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 4 +- .../blackbox/handlers/ActionHandler.java | 2 +- .../handlers/WebWhoisActionHandler.java | 7 +- .../blackbox/messages/HttpRequestMessage.java | 5 +- .../blackbox/ProbingActionTest.java | 130 +++++++------- .../blackbox/ProbingSequenceTest.java | 25 ++- .../monitoring/blackbox/ProbingStepTest.java | 6 + .../monitoring/blackbox/TestUtils.java | 2 +- .../handlers/WebWhoisActionHandlerTest.java | 9 +- 13 files changed, 176 insertions(+), 183 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 307afd34d81..e12d1f0f522 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; import java.util.Set; @@ -29,7 +30,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); + Set sequences = proberComponent.sequences(); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 1db97d1b581..fb83b236b69 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -49,7 +49,7 @@ EventLoopGroup provideEventLoopGroup() { /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides @Singleton - Class provideChannelClass() { + Class provideChannelClazz() { return NioSocketChannel.class; } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @@ -77,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - Set provideAllSequences(); + Set sequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index a8740e21c20..25c3a1c17d6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -33,10 +33,8 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -69,6 +67,8 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -85,6 +85,7 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ @@ -94,108 +95,89 @@ public abstract class ProbingAction implements Callable { public abstract String host(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } - /** - * The method that performs the work of the actual action. + * Performs the work of the actual action * - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ *

First, checks if channel is active by setting a listener to perform the bulk of the work + * when the connection future is successful.

+ * + *

Once the connection is successful, we establish which of the handlers in the pipeline is + * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when + * we receive an expected response from the server.

+ * + *

Next, we set a timer set to a specified delay. After the delay has passed, we send the + * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, + * we inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - - //ChannelPromise that we use to inform ProbingStep when we are finished. - ChannelPromise finished = channel().newPromise(); - - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - - return finished; - } /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws UndeterminedStateException { + public ChannelFuture call() { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); + + //Ensures channel has been set up with connection future as an attribute + checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + //When connection is established call super.call and set returned listener to success channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { + (ChannelFuture connectionFuture) -> { + if (connectionFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); + ActionHandler actionHandler; + try { + actionHandler = channel().pipeline().get(ActionHandler.class); + } catch (ClassCastException e) { + //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); + } + + ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> { + if (future.isSuccess()) { + finished.setSuccess(); + } else { + finished.setFailure(future.cause()); + } + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) { + logger.atInfo() + .log("Closed stale channel. Moving on to next ProbingStep"); + } else { + logger.atWarning() + .log( + "Could not close channel. Stale connection still exists."); + } + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); } else { //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( + logger.atSevere().withCause(connectionFuture.cause()).log( "Cannot connect to relay channel for %s channel: %s.", protocol().name(), this.channel()); ChannelFuture unusedFuture = channel().close(); @@ -228,7 +210,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract Protocol protocol(); - abstract Optional channel(); + abstract Channel channel(); abstract String host(); @@ -243,11 +225,11 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { + if (channel() == null) { bootstrap.handler( new ChannelInitializer() { @Override diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index ca980100067..3df536a9478 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -135,7 +135,7 @@ public void accept(Token token) { try { //call the generated action future = currentAction.call(); - } catch(UndeterminedStateException e) { + } catch(Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index c5e41fea38b..2e640338511 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -184,10 +184,10 @@ static SslClientInitializer provideSslClientInitializer(SslPro @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClass){ + Class channelClazz){ return new Bootstrap() .group(eventLoopGroup) - .channel(channelClass); + .channel(channelClazz); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 8a108b81006..55c9123e3a5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -46,7 +46,7 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler testHandlerProvider = new TestProvider<>(testHandler); private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - private ProbingAction newChannelAction; - private ProbingAction existingChannelAction; - private EmbeddedChannel channel; - private Protocol protocol; - /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** Sets up a {@link Protocol} corresponding to when a new connection is created */ - private void setupNewChannelProtocol() { - protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - } - /** Sets up a {@link Protocol} corresponding to when a new connection exists */ - private void setupExistingChannelProtocol() { - protocol = Protocol.builder() + + + + @Test + public void testBehavior_existingChannel() throws UndeterminedStateException { + //setup + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up a Protocol corresponding to when a connection exists. + Protocol protocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) .build(); - } - - /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ - private void setupNewChannelAction() { - newChannelAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - } - - private void setupChannel() { - channel = new EmbeddedChannel(); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ - private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ProbingAction.builder() + // Sets up a ProbingAction that creates a channel using test specified attributes. + ProbingAction action = ProbingAction.builder() .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) .setHost("") .build(); - } - - @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { - //setup - setupChannel(); - setupExistingChannelProtocol(); - channel.pipeline().addLast(conversionHandler); - channel.pipeline().addLast(testHandler); - setupExistingChannelAction(channel); + //tests main function of ProbingAction + ChannelFuture future = action.call(); - ChannelFuture future = existingChannelAction.call(); - - //Ensures that we pass in the right message to the channel and haven't marked the future as success yet - Object msg = channel.readOutbound(); + //Obtains the outboundMessage passed through pipeline after delay + Object msg = null; + while (msg == null) { + msg = channel.readOutbound(); + } + //tests the passed message is exactly what we expect assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - assertThat(response).isEqualTo(TEST_MESSAGE); - assertThat(future.isSuccess()).isFalse(); + String request = ((ByteBuf) msg).toString(UTF_8); + assertThat(request).isEqualTo(TEST_MESSAGE); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -158,18 +122,40 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { @Test public void testSuccess_newChannel() throws Exception { //setup - setupNewChannelProtocol(); + + LocalAddress address = new LocalAddress(ADDRESS_NAME); + Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + // Sets up a Protocol corresponding to when a new connection is created. + Protocol protocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) + .build(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - setupNewChannelAction(); - ChannelFuture future = newChannelAction.call(); + + // Sets up a ProbingAction with existing channel using test specified attributes. + ProbingAction action = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) + .build(); + + //tests main function of ProbingAction + ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.sync(); + future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()); + assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 8d9e45c6a66..e5f91a300d6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -18,27 +18,44 @@ import static google.registry.testing.JUnitBackports.assertThrows; import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.TestUtils.TestToken; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import java.net.SocketAddress; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; @RunWith(JUnit4.class) public class ProbingSequenceTest { private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new ProbingSequenceTestToken(); + private Token testToken = new TestToken("") { + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + }; + private void setupMock(ProbingStep mock, ProbingStep nextStep) { + Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + } /** * Custom {@link ProbingStep} subclass that acts as a mock * step, so we can test how well {@link ProbingSequence} builds * a linked list of {@link ProbingStep}s from their {@link Builder}s. */ + private static class TestStep extends ProbingStep { private String marker; @@ -92,9 +109,9 @@ public void specialAccept(Token token) { @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 73b104ae5dc..256eeb0b29d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -45,6 +45,7 @@ import javax.inject.Provider; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ public class ProbingStepTest { @@ -191,6 +192,11 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); + Object msg = channel.readOutbound(); + + while (msg == null) { + msg = channel.readOutbound(); + } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index cc8e1512fe9..ef9926a7620 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -204,7 +204,7 @@ public String toString() { } /** Basic outline for {@link Token} instances to be used in tests */ - private static abstract class TestToken extends Token { + static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 2483bd65b1f..5fa39b1da83 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -41,7 +41,6 @@ import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; import org.joda.time.Duration; @@ -156,7 +155,7 @@ public void testBasic_responseOk() throws Exception { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); @@ -187,7 +186,7 @@ public void testBasic_responseFailure_badRequest() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -218,7 +217,7 @@ public void testBasic_responseFailure_badURL() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -251,7 +250,7 @@ public void testBasic_redirectCloseChannel() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early From 3312240ae2200e141d5f3f6df69208a3b0f1bdea Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 15:45:32 -0400 Subject: [PATCH 135/337] Modified tests for WebWhois according to changes suggested by laijiang. --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 2 - .../monitoring/blackbox/ProbingAction.java | 1 - .../monitoring/blackbox/WebWhoisModule.java | 10 +- .../blackbox/ProbingActionTest.java | 20 +- .../blackbox/ProbingSequenceTest.java | 120 ++++------- .../monitoring/blackbox/ProbingStepTest.java | 187 ++++++++--------- .../blackbox/TestServers/TestServer.java | 38 ---- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 142 +------------ .../monitoring/blackbox/TokenTest.java | 59 ------ .../blackbox/handlers/ConversionHandler.java | 6 +- .../blackbox/handlers/NettyRule.java | 46 +++- .../handlers/SslClientInitializerTest.java | 5 - .../blackbox/handlers/TestActionHandler.java | 7 +- .../handlers/WebWhoisActionHandlerTest.java | 197 +++++++----------- .../blackbox/messages/TestMessage.java | 4 + 17 files changed, 264 insertions(+), 589 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index e12d1f0f522..5ca423c29cc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -30,7 +29,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.sequences(); + ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index fb83b236b69..f9db4865f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,11 +14,9 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 25c3a1c17d6..0265390fafe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -138,7 +138,6 @@ public ChannelFuture call() { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); timer.newTimeout(timeout -> { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 2e640338511..de041afad38 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,14 +17,11 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -33,10 +30,7 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index b5d8f7599c4..ec5ee5d77ec 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,17 +20,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -39,9 +37,9 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; import javax.inject.Provider; import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,10 +72,9 @@ public class ProbingActionTest { public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - + @Ignore @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { + public void testBehavior_existingChannel() { //setup EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -95,7 +92,7 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost("") .build(); @@ -112,6 +109,9 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { String request = ((ByteBuf) msg).toString(UTF_8); assertThat(request).isEqualTo(TEST_MESSAGE); + // Ensures that we haven't marked future as done until response is received. + assertThat(future.isDone()).isFalse(); + //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); assertThat(future.isSuccess()).isTrue(); @@ -143,7 +143,7 @@ public void testSuccess_newChannel() throws Exception { .setBootstrap(bootstrap) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost(ADDRESS_NAME) .build(); @@ -151,7 +151,7 @@ public void testSuccess_newChannel() throws Exception { ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index e5f91a300d6..5c4452df7b3 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -15,17 +15,11 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; -import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; -import google.registry.monitoring.blackbox.TestUtils.TestToken; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import java.net.SocketAddress; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,85 +27,31 @@ @RunWith(JUnit4.class) public class ProbingSequenceTest { - private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new TestToken("") { - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - }; - - private void setupMock(ProbingStep mock, ProbingStep nextStep) { - Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + private ProbingStep setupMock() { + ProbingStep mock = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(mock).nextStep(); + return mock; } - /** - * Custom {@link ProbingStep} subclass that acts as a mock - * step, so we can test how well {@link ProbingSequence} builds - * a linked list of {@link ProbingStep}s from their {@link Builder}s. - */ - - private static class TestStep extends ProbingStep { - private String marker; - - /** We implement all abstract methods to simply return null, as we have no use for them here. */ - @Override - Duration duration() { - return null; - } - @Override - Protocol protocol() { - return null; - } + private static class Wrapper { - @Override - OutboundMessageType messageTemplate() { - return null; - } + T data; - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ - @Override - Bootstrap bootstrap() { - return null; - } - - public TestStep(String marker) { - this.marker = marker; - } - - /** - * On a call to accept, we modify the token to reflect what the current step is, so we can get - * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated - * in order. - */ - @Override - public void accept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - if (!isLastStep) { - nextStep().accept(token); - } else { - ((TestStep)nextStep()).specialAccept(token); - } - } - - /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ - public void specialAccept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - return; + public Wrapper(T data) { + this.data = data; } } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = Mockito.mock(ProbingStep.class); - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) @@ -119,16 +59,25 @@ public void testSequenceBasicConstruction_Success() { .addStep(thirdStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(thirdStep); + assertThat(thirdStep.nextStep()).isEqualTo(firstStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); + assertThat(wrapper.data).isTrue(); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(thirdStep) @@ -137,9 +86,16 @@ public void testSequenceAdvancedConstruction_Success() { .addStep(firstStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(firstStep); + assertThat(thirdStep.nextStep()).isEqualTo(secondStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); + assertThat(wrapper.data).isTrue(); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 256eeb0b29d..91a113940e8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,18 +11,19 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.TestUtils.dummyStep; -import static google.registry.monitoring.blackbox.TestUtils.testStep; -import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; import google.registry.monitoring.blackbox.TestUtils.TestProvider; @@ -30,19 +31,20 @@ import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; +import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; @@ -51,18 +53,18 @@ public class ProbingStepTest { /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final static String ADDRESS_NAME = "TEST_ADDRESS"; + private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final static int PROTOCOL_PORT = 0; + private final static String TEST_MESSAGE = "TEST_MESSAGE"; + private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -73,117 +75,108 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(ADDRESS_NAME); + /** + * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} + * is called, it just marks the supplied future as succeeded, returning the requisite token. + */ + private ProbingStep dummyStep() { + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(dummyStep).nextStep(); + return dummyStep; } - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); - dummyStep = dummyStep(eventLoopGroup); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - } + @Test + public void testNewChannel() throws Exception { + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() + // Sets up Protocol for when we create a new channel. + Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); - } - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) .build(); - } - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - //there should be no next step - assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); - } + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); - @Test - public void testNewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + //Set up blackbox server that receives our messages then echoes them back to us + nettyRule.setUpServer(address); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); + verify(dummyStep, times(1)).accept(any(Token.class)); } + @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupChannel(); - setupExistingChannelToken(); + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); + + // Sets up Protocol for when a channel already exists. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) + .build(); + + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) + .build(); + + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + + // Sets up an embedded channel to contain the two handlers we created already. + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + + //Assures that the channel has a succeeded connectionFuture. + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. + Token testToken = new ExistingChannelToken(channel, ""); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -200,17 +193,13 @@ public void testWithSequence_ExistingChannel() throws Exception { //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); + //At this point, we should have received the message, so the future obtained should be marked + // as a success + verify(dummyStep, times(1)).accept(any(Token.class)); - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index a4474b6b8b5..12e25a6bc6c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -14,24 +14,16 @@ package google.registry.monitoring.blackbox.TestServers; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; - import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform @@ -65,35 +57,5 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index e7f125bb906..4da75b31c25 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -74,7 +75,7 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends ChannelDuplexHandler { + static class RedirectHandler extends SimpleChannelInboundHandler { private String redirectInput; private String destinationInput; @@ -90,8 +91,7 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - HttpRequest request = (HttpRequest) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index ef9926a7620..2567a7cc155 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,42 +16,24 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMethod;; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.concurrent.DefaultPromise; -import java.net.SocketAddress; import javax.inject.Provider; -import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { - static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -76,33 +58,13 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); + response.headers().set("content-type", "text/plain"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); return response; } @@ -121,88 +83,6 @@ public E get() { } } - /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ - public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { - - String message; - - public DuplexMessageTest() { - message = ""; - } - - public DuplexMessageTest(String msg) { - message = msg; - } - - @Override - public String toString() { - return message; - } - - @Override - public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { - message = args[0]; - return this; - } - } - - /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .build(); - - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); - } - - /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { - private DefaultPromise future; - - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; - } - - @Override - public void accept(Token token) { - future.setSuccess(token); - } - public DefaultPromise getFuture() { - return future; - } - - @Override - public String toString() { - return "Dummy Step"; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; @@ -251,21 +131,5 @@ public Channel channel() { return channel; } } - - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java deleted file mode 100644 index 295bb809a13..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) - */ -@RunWith(JUnit4.class) -public class TokenTest { - - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - - public Token webToken = new WebWhoisToken(TEST_DOMAINS); - - @Test - public void testWebToken_MessageModificationSuccess() { - //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); - - //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { - throw new RuntimeException(e); - } - - - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 196141bb875..c9d337d6ad8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -32,7 +32,7 @@ * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +40,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 1d14cf131e6..86b54d9a07d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -25,14 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -44,7 +41,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -55,7 +51,7 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + *

Code based on and almost identical to {@code NettyRule} in the proxy. * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -83,10 +79,12 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + ImmutableList.builder().add(handlers).add(echoHandler).build()); } /** Sets up a client channel connecting to the give local address. */ @@ -124,7 +122,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertThatCustomWorks(String message) throws Exception { + public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -165,6 +163,38 @@ ThrowableSubject assertThatClientRootCause() { } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** + * Saves any inbound error as the cause of the promise failure. + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 83c8e132f07..523fb228752 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -22,12 +22,7 @@ import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 3ecbdcc0d06..95b06e623d1 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -25,17 +25,16 @@ */ public class TestActionHandler extends ActionHandler { - private String receivedMessage; + private InboundMessageType receivedMessage; @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage.toString(); + receivedMessage = inboundMessage; super.channelRead0(ctx, inboundMessage); } - @Override - public String toString() { + public InboundMessageType getResponse() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 5fa39b1da83..3667f3f3d9a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -20,7 +20,6 @@ import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; -import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; @@ -28,13 +27,11 @@ import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; @@ -56,6 +53,7 @@ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -65,11 +63,12 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of()) + private final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( + null, null, null, null)))) .setName("http") .setPersistentConnection(false) - .setPort(HTTPS_PORT) + .setPort(HTTP_PORT) .build(); @@ -78,14 +77,13 @@ public class WebWhoisActionHandlerTest { private ActionHandler actionHandler; private ProbingAction probingAction; private Provider actionHandlerProvider; + private Protocol initialProtocol; + private HttpRequestMessage msg; - private String generateLocalAddress(String addressString) { - String modifiedAddress = addressString + System.currentTimeMillis(); - address = new LocalAddress(modifiedAddress); - return modifiedAddress; - } - /** Creates default protocol with empty list of handlers and specified other inputs */ + /** + * Creates default protocol with empty list of handlers and specified other inputs + */ private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() .setName(name) @@ -95,7 +93,9 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect .build(); } - /** Initializes new WebWhoisActionHandler */ + /** + * Initializes new WebWhoisActionHandler + */ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, @@ -106,12 +106,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT actionHandlerProvider = new TestProvider<>(actionHandler); } - /** Sets up testing channel with requisite attributes */ + /** + * Sets up testing channel with requisite attributes + */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -119,18 +120,9 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .group(group) .channel(LocalChannel.class); } - /**Sets up probingAction for when testing redirection */ - private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setHost(TARGET_HOST) - .setChannel(channel) - .build(); - } - private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { + private void setupProbingActionWithoutChannel(Protocol protocol, + HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) @@ -140,171 +132,124 @@ private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMess .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + private void setupLocalServer(String redirectInput, String destinationInput, + EventLoopGroup group) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testBasic_responseOk() throws Exception { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { + msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, true); + initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + } + + @Test + public void testBasic_responseOk() { + //setup + setup("", null, true); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure_badRequest() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseBad", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage( + makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same assertThat(future.cause() instanceof FailureException).isTrue(); } - @Test - public void testBasic_responseFailure_badURL() { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseError", 0, true); - setupChannel(initialProtocol, msg); - - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, and event is success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); - } @Test - public void testBasic_redirectCloseChannel() { + public void testBasic_responseFailure_badURL() { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - //checks that future has not been set to successful or a failure - assertThat(testPromise.isSuccess()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - + //assesses that listener is triggered, and event is success + assertThat(future.isDone()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + //ensures Protocol is the same + assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_responseOk() throws UndeterminedStateException { - //setup + public void testAdvanced_redirect() { + // Sets up EventLoopGroup with 1 thread to be blocking. EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + // Sets up embedded channel. + setup("", makeBootstrap(group), false); + setupChannel(initialProtocol, msg); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); - } + // Initializes LocalAddress with unique String. + String host = TARGET_HOST + System.currentTimeMillis(); + address = new LocalAddress(host); - @Test - public void testAdvanced_responseFailure() throws UndeterminedStateException { - //setup - EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); + //stores future + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); + + // Sets up the local server that the handler will be redirected to. setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + FullHttpResponse response = + new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, + HTTP_REDIRECT + host, true, false)); + + //checks that future has not been set to successful or a failure + assertThat(future.isDone()).isFalse(); + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); //assesses that we successfully received good response and protocol is unchanged - assertThrows(FailureException.class, future::syncUninterruptibly); + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index 922c3052bda..c31a9d336bd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,6 +24,10 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; + public TestMessage() { + this(""); + } + public TestMessage(String msg) { message = msg; } From 9c6235f85b85a710157d317995e8348f39a15b41 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 16:42:43 -0400 Subject: [PATCH 136/337] Removed TestProvider from TestUtils. --- .../blackbox/ProbingActionTest.java | 7 ++-- .../monitoring/blackbox/ProbingStepTest.java | 11 +++--- .../blackbox/TestServers/TestServer.java | 3 -- .../monitoring/blackbox/TestUtils.java | 17 --------- .../handlers/WebWhoisActionHandlerTest.java | 36 ++++++------------- .../blackbox/messages/TestMessage.java | 4 --- 6 files changed, 18 insertions(+), 60 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index ec5ee5d77ec..f7857dd80f9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -64,8 +63,8 @@ public class ProbingActionTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + private Provider testHandlerProvider = () -> testHandler; + private Provider conversionHandlerProvider = () -> conversionHandler; /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -156,7 +155,7 @@ public void testSuccess_newChannel() throws Exception { future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 91a113940e8..1f09dd13553 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -90,9 +89,8 @@ private ProbingStep dummyStep() { @Test public void testNewChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when we create a new channel. Protocol testProtocol = Protocol.builder() @@ -142,9 +140,8 @@ public void testNewChannel() throws Exception { @Test public void testWithSequence_ExistingChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when a channel already exists. Protocol testProtocol = Protocol.builder() diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 12e25a6bc6c..46615a506fb 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -29,15 +29,12 @@ * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { - private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - this.localAddress = localAddress; - //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 2567a7cc155..50c60d9fc52 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -21,7 +21,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -29,7 +28,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Provider; /** Utility class for various helper methods used in testing. */ public class TestUtils { @@ -68,21 +66,6 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ - public static class TestProvider implements Provider { - - private E obj; - - public TestProvider(E obj) { - this.obj = obj; - } - - @Override - public E get() { - return obj; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 3667f3f3d9a..33eb190a66a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -25,7 +25,6 @@ import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; @@ -64,18 +63,16 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( - null, null, null, null)))) + .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( + null, null, null, null))) .setName("http") .setPersistentConnection(false) .setPort(HTTP_PORT) .build(); - private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; - private ProbingAction probingAction; private Provider actionHandlerProvider; private Protocol initialProtocol; private HttpRequestMessage msg; @@ -103,13 +100,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT STANDARD_PROTOCOL, messageTemplate ); - actionHandlerProvider = new TestProvider<>(actionHandler); + actionHandlerProvider = () -> actionHandler; } /** * Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + private void setupChannel(Protocol protocol) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -121,19 +118,8 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } - private void setupProbingActionWithoutChannel(Protocol protocol, - HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(addressString) - .build(); - } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group) { + EventLoopGroup group, LocalAddress address) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } @@ -148,7 +134,7 @@ private void setup(String hostName, Bootstrap bootstrap, boolean persistentConne public void testBasic_responseOk() { //setup setup("", null, true); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -169,7 +155,7 @@ public void testBasic_responseOk() { public void testBasic_responseFailure_badRequest() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -195,7 +181,7 @@ public void testBasic_responseFailure_badRequest() { public void testBasic_responseFailure_badURL() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -224,18 +210,18 @@ public void testAdvanced_redirect() { // Sets up embedded channel. setup("", makeBootstrap(group), false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); // Initializes LocalAddress with unique String. String host = TARGET_HOST + System.currentTimeMillis(); - address = new LocalAddress(host); + LocalAddress address = new LocalAddress(host); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group); + setupLocalServer("", host, group, address); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index c31a9d336bd..922c3052bda 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,10 +24,6 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; - public TestMessage() { - this(""); - } - public TestMessage(String msg) { message = msg; } From 1520444c45a9534f200be30015c28a597808ae46 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 09:46:27 -0400 Subject: [PATCH 137/337] Rebased to master --- .../monitoring/blackbox/handlers/ActionHandler.java | 7 +++++-- .../monitoring/blackbox/TestServers/WebWhoisServer.java | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 55c9123e3a5..eda82c59a37 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -33,8 +33,11 @@ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} - * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * of the error. If the error is an instance of a {@link FailureException} {@code finished} is + * marked as a failure with cause {@link FailureException}. If it is any other type of error, it + * is treated as an {@link UndeterminedStateException} and {@code finished} set as a failure with + * the same cause as what caused the exception. Lastly, if no error is thrown, we know the action + * completed as a success, and, as such, we mark {@code finished} as a success.

* *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 4da75b31c25..28b36190a7e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; From 498f58658b4b4eac04e1279436016a3ea8c2aafd Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 11:26:33 -0400 Subject: [PATCH 138/337] Updated issues in rebasing --- core/src/main/java/google/registry/ui/package-info.java | 1 - core/src/main/java/google/registry/xjc/package-info.java | 1 - 2 files changed, 2 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..ddff37c6807 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -14,4 +14,3 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.ui; - diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..5b5456585cc 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -14,4 +14,3 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.xjc; - From 2764dda28a49fb4cf7d575880f63f89c563750d6 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 12:33:30 -0400 Subject: [PATCH 139/337] Minor style change on prober/build.gradle --- core/src/main/java/google/registry/cron/package-info.java | 2 +- core/src/main/java/google/registry/xml/package-info.java | 2 +- prober/build.gradle | 1 - .../registry/monitoring/blackbox/handlers/ActionHandler.java | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/google/registry/cron/package-info.java b/core/src/main/java/google/registry/cron/package-info.java index 49b18ca2885..459f2513f93 100644 --- a/core/src/main/java/google/registry/cron/package-info.java +++ b/core/src/main/java/google/registry/cron/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xml/package-info.java b/core/src/main/java/google/registry/xml/package-info.java index b3f27868b91..f8e42585ecc 100644 --- a/core/src/main/java/google/registry/xml/package-info.java +++ b/core/src/main/java/google/registry/xml/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/prober/build.gradle b/prober/build.gradle index 70b8e2a6b8b..3652390d0ba 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -53,4 +53,3 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index eda82c59a37..8f2319b3d39 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -60,7 +60,7 @@ public void handlerAdded(ChannelHandlerContext ctx) { finished = ctx.newPromise(); } - /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ + /** Marks {@link ChannelPromise} as success */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { From 201410825e3c47191c67e70d68e106d0063228c3 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 15:11:53 -0400 Subject: [PATCH 140/337] Fixed warnings for java compilation --- .../registry/monitoring/blackbox/ProbingAction.java | 11 +++++------ .../registry/monitoring/blackbox/ProbingStep.java | 4 ++-- .../google/registry/monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/handlers/ActionHandler.java | 6 +++--- .../blackbox/handlers/WebWhoisActionHandler.java | 2 +- .../blackbox/messages/HttpRequestMessage.java | 3 ++- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 0265390fafe..c7645f29e6a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -67,8 +67,6 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -142,13 +140,14 @@ public ChannelFuture call() { timer.newTimeout(timeout -> { // Write appropriate outboundMessage to pipeline - channel().writeAndFlush(outboundMessage()); + ChannelFuture unusedFutureWriteAndFlush = + channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( future -> { if (future.isSuccess()) { - finished.setSuccess(); + ChannelFuture unusedFuture = finished.setSuccess(); } else { - finished.setFailure(future.cause()); + ChannelFuture unusedFuture = finished.setFailure(future.cause()); } }, //If we don't have a persistent connection, close the connection to this channel @@ -276,7 +275,7 @@ private static void addHandlers( @Override - public String toString() { + public final String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 3df536a9478..332a8d0de04 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -105,7 +105,7 @@ private ProbingAction generateAction(Token token) throws UndeterminedStateExcept /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { - return (isLastStep) ? token.next() : token; + return isLastStep ? token.next() : token; } /** @@ -167,7 +167,7 @@ public void accept(Token token) { } @Override - public String toString() { + public final String toString() { return String.format("ProbingStep with Protocol: %s\n" + "OutboundMessage: %s\n", protocol(), diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 92470ef62c8..b430d79507a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -58,7 +58,7 @@ public abstract static class Builder { } @Override - public String toString() { + public final String toString() { return String.format( "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", name(), diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 8f2319b3d39..6b6dad914a4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -65,7 +65,7 @@ public void handlerAdded(ChannelHandlerContext ctx) { public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - finished.setSuccess(); + ChannelFuture unusedFuture = finished.setSuccess(); } /** @@ -86,14 +86,14 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atInfo().log(cause.getMessage()); //As always, inform the ProbingStep that we successfully completed this action - finished.setFailure(cause); + ChannelFuture unusedFuture = finished.setFailure(cause); } else { //On UndeterminedStateException, we know the response type is an error. //Since it wasn't a success, we still log what caused the ERROR logger.atWarning().log(cause.getMessage()); - finished.setFailure(cause); + ChannelFuture unusedFuture = finished.setFailure(cause); //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 34eac2a0118..de20c6b9269 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -86,7 +86,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { + if (response.status().equals(HttpResponseStatus.OK)) { logger.atInfo().log("Received Successful HttpResponseStatus"); logger.atInfo().log("Response Received: " + response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 5e9300d0f34..8d285811e0d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,6 +19,7 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import java.util.Arrays; import javax.inject.Inject; /** @@ -69,7 +70,7 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx throw new IllegalArgumentException( String.format( "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + args, args.length)); + + " Received %d arguments instead of: " + Arrays.toString(args), args.length)); } } From bbc411327198a9c10496011649867415433c1c94 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 17:01:14 -0400 Subject: [PATCH 141/337] Fixed files to pass all style tests --- .../registry/monitoring/blackbox/Prober.java | 10 +- .../monitoring/blackbox/ProberModule.java | 32 ++++-- .../monitoring/blackbox/ProbingAction.java | 108 +++++++++++------- .../monitoring/blackbox/ProbingSequence.java | 39 ++++--- .../monitoring/blackbox/ProbingStep.java | 75 +++++++----- .../monitoring/blackbox/Protocol.java | 16 ++- .../monitoring/blackbox/WebWhoisModule.java | 80 +++++++++---- .../exceptions/ConnectionException.java | 4 +- .../UndeterminedStateException.java | 5 +- .../blackbox/handlers/ActionHandler.java | 48 +++++--- .../handlers/SslClientInitializer.java | 11 +- .../handlers/WebWhoisActionHandler.java | 53 ++++++--- .../handlers/WebWhoisMessageHandler.java | 21 ++-- .../blackbox/messages/HttpRequestMessage.java | 19 ++- .../messages/HttpResponseMessage.java | 6 +- .../blackbox/messages/InboundMessageType.java | 4 +- .../messages/OutboundMessageType.java | 10 +- .../monitoring/blackbox/tokens/Token.java | 41 ++++--- .../blackbox/tokens/WebWhoisToken.java | 36 ++++-- .../blackbox/ProbingActionTest.java | 17 ++- .../monitoring/blackbox/ProbingStepTest.java | 37 +++--- .../blackbox/TestServers/TestServer.java | 58 ---------- .../blackbox/TestServers/WebWhoisServer.java | 106 ----------------- .../monitoring/blackbox/TestUtils.java | 32 ++++-- .../blackbox/handlers/ConversionHandler.java | 16 ++- .../blackbox/handlers/NettyRule.java | 37 +++--- .../handlers/SslClientInitializerTest.java | 36 +++--- .../blackbox/handlers/TestActionHandler.java | 4 +- .../handlers/WebWhoisActionHandlerTest.java | 18 +-- .../blackbox/tokens/WebWhoisTokenTest.java | 2 - 30 files changed, 526 insertions(+), 455 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 5ca423c29cc..433d7361d5b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -18,12 +18,16 @@ import google.registry.monitoring.blackbox.ProberModule.ProberComponent; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by + * Dagger. */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + /** + * Main Dagger Component + */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() + .build(); public static void main(String[] args) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index f9db4865f78..df8b5fdbabd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -28,36 +28,50 @@ import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores - * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. + * Dagger main module, which {@link Provides} all objects that are shared between sequences and + * stores {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link + * ProbingSequence}. */ @Module public class ProberModule { - /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + /** + * Default {@link Duration} chosen to be time between each {@link ProbingAction} call. + */ private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ + /** + * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. + */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + /** + * {@link Provides} one global {@link Channel} class that is used to construct a {@link + * io.netty.bootstrap.Bootstrap}. + */ @Provides @Singleton Class provideChannelClazz() { return NioSocketChannel.class; } - /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ + + /** + * {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. + */ @Provides @Singleton Duration provideDuration() { return DEFAULT_DURATION; } - /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ + /** + * {@link Provides} the {@link SslProvider} used by instances of {@link + * google.registry.monitoring.blackbox.handlers.SslClientInitializer} + */ @Provides @Singleton static SslProvider provideSslProvider() { @@ -65,7 +79,9 @@ static SslProvider provideSslProvider() { return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - /** Root level {@link Component} that provides each {@link ProbingSequence}. */ + /** + * Root level {@link Component} that provides each {@link ProbingSequence}. + */ @Singleton @Component( modules = { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index c7645f29e6a..cdb099e4a76 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -26,40 +26,42 @@ import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; +import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; import javax.inject.Provider; +import org.joda.time.Duration; /** * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the - * task has been completed

+ * to perform its specified task, and return the {@link ChannelFuture} that will be informed when + * the task has been completed

* - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. - * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} - * gives the outline and {@link ProbingAction} gives the details of that connection.

+ *

Is an immutable class, as it is comprised of the tools necessary for making a specific type + * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall + * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the + * details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes + * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when + * informed that the connection is successful. If the channel is supplied, the connection future is + * automatically set to successful.

*/ @AutoValue @@ -67,32 +69,51 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** + * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when + * channel is active. + */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey + .valueOf("CONNECTION_FUTURE_KEY"); - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + /** + * {@link AttributeKey} in channel that gives the information of the channel's host. + */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey + .valueOf("REMOTE_ADDRESS_KEY"); - /** {@link Timer} that rate limits probing */ + /** + * {@link Timer} that rate limits probing + */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ + /** + * Actual {@link Duration} of this delay + */ public abstract Duration delay(); - /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ + /** + * {@link OutboundMessageType} instance that we write and flush down pipeline to server + */ public abstract OutboundMessageType outboundMessage(); - /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + /** + * {@link Channel} object that either created by or passed into this {@link ProbingAction} + * instance + */ @Nullable public abstract Channel channel(); - /** The {@link Protocol} instance that specifies type of connection */ + /** + * The {@link Protocol} instance that specifies type of connection + */ public abstract Protocol protocol(); - /** The hostname of the remote host we have a connection or will make a connection to */ + /** + * The hostname of the remote host we have a connection or will make a connection to + */ public abstract String host(); - /** * Performs the work of the actual action * @@ -111,7 +132,10 @@ public abstract class ProbingAction implements Callable { */ - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + /** + * Method that calls on {@code performAction} when it is certain channel connection is + * established. + */ @Override public ChannelFuture call() { //ChannelPromise that we return @@ -132,7 +156,8 @@ public ChannelFuture call() { try { actionHandler = channel().pipeline().get(ActionHandler.class); } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + //If we don't actually have an ActionHandler instance, we have an issue, and throw + // an UndeterminedStateException logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } @@ -150,7 +175,8 @@ public ChannelFuture call() { ChannelFuture unusedFuture = finished.setFailure(future.cause()); } }, - //If we don't have a persistent connection, close the connection to this channel + //If we don't have a persistent connection, close the connection to this + // channel future -> { if (!protocol().persistentConnection()) { @@ -163,7 +189,8 @@ public ChannelFuture call() { } else { logger.atWarning() .log( - "Could not close channel. Stale connection still exists."); + "Could not close channel. Stale connection still exists" + + "."); } } ); @@ -186,9 +213,12 @@ public ChannelFuture call() { } - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + /** + * {@link AutoValue.Builder} that does work of creating connection when not already present. + */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; public Builder setBootstrap(Bootstrap bootstrap) { @@ -223,7 +253,8 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); + checkArgument(channel() == null ^ bootstrap == null, + "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel @@ -273,14 +304,13 @@ private static void addHandlers( } - @Override public final String toString() { return String.format( - "ProbingAction with delay: %d\n" + - "outboundMessage: %s\n" + - "protocol: %s\n" + - "host: %s\n", + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 91c4165c068..175cf4dcfa5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -23,16 +23,21 @@ * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * * - *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

+ *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} + * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one + * is the first repeated step.

* - *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

+ *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once + * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest + * of the work.

*/ public class ProbingSequence { + private ProbingStep firstStep; - /**Each {@link ProbingSequence} requires a start token to begin running. */ + /** + * Each {@link ProbingSequence} requires a start token to begin running. + */ private Token startToken; public void start() { @@ -41,8 +46,8 @@ public void start() { } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link + * Bootstrap}. */ public static class Builder { @@ -57,33 +62,37 @@ public Builder(Token startToken) { } /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, - * built, and pointed to by the previous {@link ProbingStep} added. + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, built, and pointed to by + * the previous {@link ProbingStep} added. */ public Builder addStep(ProbingStep step) { - if (currentStep == null) + if (currentStep == null) { firstStep = step; - else + } else { currentStep.nextStep(step); + } currentStep = step; return this; } - /** We take special note of the first repeated step. */ + /** + * We take special note of the first repeated step. + */ public Builder markFirstRepeated() { firstRepeatedStep = currentStep; return this; } /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and - * calls private constructor to create {@link ProbingSequence}. + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private + * constructor to create {@link ProbingSequence}. */ public ProbingSequence build() { - if (firstRepeatedStep == null) + if (firstRepeatedStep == null) { firstRepeatedStep = firstStep; + } currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 332a8d0de04..98867c01220 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -17,47 +17,59 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import java.util.function.Consumer; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step - * in {@link ProbingSequence}. + * {@link AutoValue} class that represents generator of actions performed at each step in {@link + * ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. - * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, - * generates a new {@link ProbingAction} to call.

- * + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} + * instances. It then modifies these components on each loop iteration with the consumed {@link + * Token} and from that, generates a new {@link ProbingAction} to call.

*/ @AutoValue public abstract class ProbingStep implements Consumer { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Necessary boolean to inform when to obtain next {@link Token}*/ + /** + * Necessary boolean to inform when to obtain next {@link Token} + */ protected boolean isLastStep = false; private ProbingStep nextStep; - /** Time delay duration between actions. */ + /** + * Time delay duration between actions. + */ abstract Duration duration(); - /** {@link Protocol} type for this step. */ + /** + * {@link Protocol} type for this step. + */ abstract Protocol protocol(); - /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ + /** + * {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. + */ abstract OutboundMessageType messageTemplate(); - /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ + /** + * {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation + * of new channels. + */ abstract Bootstrap bootstrap(); + /** Default {@link AutoValue.Builder} for {@link ProbingStep}. */ @AutoValue.Builder - public static abstract class Builder { + public abstract static class Builder { + public abstract Builder setDuration(Duration value); public abstract Builder setProtocol(Protocol value); @@ -85,7 +97,9 @@ ProbingStep nextStep() { return this.nextStep; } - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ + /** + * Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} + */ private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() @@ -94,29 +108,33 @@ private ProbingAction generateAction(Token token) throws UndeterminedStateExcept .setOutboundMessage(message) .setHost(token.host()); - if (token.channel() != null) + if (token.channel() != null) { probingActionBuilder.setChannel(token.channel()); - else + } else { probingActionBuilder.setBootstrap(bootstrap()); + } return probingActionBuilder.build(); } - /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ + /** + * On the last step, gets the next {@link Token}. Otherwise, uses the same one. + */ private Token generateNextToken(Token token) { return isLastStep ? token.next() : token; } /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the + * action. * * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. * *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

+ * we note an error. Otherwise, if the future marked as finished when the action is completed is + * marked as a success, we note a success. Otherwise, if the cause of failure will either be a + * failure or error.

*/ @Override public void accept(Token token) { @@ -124,18 +142,17 @@ public void accept(Token token) { //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(UndeterminedStateException e) { + } catch (UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - ChannelFuture future; try { //call the generated action future = currentAction.call(); - } catch(Exception e) { + } catch (Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); @@ -144,7 +161,6 @@ public void accept(Token token) { return; } - future.addListener(f -> { if (f.isSuccess()) { //On a successful result, we log as a successful step, and not a success @@ -155,9 +171,10 @@ public void accept(Token token) { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - if (protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token + if (protocol().persistentConnection()) { + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + } //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); @@ -168,8 +185,8 @@ public void accept(Token token) { @Override public final String toString() { - return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n", + return String.format("ProbingStep with Protocol: %s\n" + + "OutboundMessage: %s\n", protocol(), messageTemplate().getClass().getName()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index b430d79507a..676fd80d740 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -26,23 +26,30 @@ @AutoValue public abstract class Protocol { - /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + /** + * {@link AttributeKey} that lets channel reference {@link Protocol} that created it. + */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); public abstract String name(); public abstract int port(); - /** The {@link ChannelHandler} providers to use for the protocol, in order. */ + /** + * The {@link ChannelHandler} providers to use for the protocol, in order. + */ abstract ImmutableList> handlerProviders(); - /** Boolean that notes if connection associated with Protocol is persistent.*/ + /** + * Boolean that notes if connection associated with Protocol is persistent. + */ abstract boolean persistentConnection(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } + /** Default {@link AutoValue.Builder} for {@link Protocol}. */ @AutoValue.Builder public abstract static class Builder { @@ -50,7 +57,8 @@ public abstract static class Builder { public abstract Builder setPort(int num); - public abstract Builder setHandlerProviders(ImmutableList> providers); + public abstract Builder setHandlerProviders( + ImmutableList> providers); public abstract Builder setPersistentConnection(boolean value); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index de041afad38..55fc7cf71a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -36,7 +36,9 @@ import javax.inject.Singleton; import org.joda.time.Duration; -/** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ +/** + * A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. + */ @Module public class WebWhoisModule { @@ -45,23 +47,39 @@ public class WebWhoisModule { private static final String HTTP_PROTOCOL_NAME = "http"; private static final String HTTPS_PROTOCOL_NAME = "https"; - /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + /** + * Standard length of messages used by Proxy. Equates to 0.5 MB. + */ private static final int maximumMessageLengthBytes = 512 * 1024; - /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ + /** + * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. + */ @Qualifier - public @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol { - /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ + } + + /** + * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. + */ @Qualifier - public @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol { + + } - /** Dagger qualifier to provide any WebWhois related bindings. */ + /** + * Dagger qualifier to provide any WebWhois related bindings. + */ @Qualifier - public @interface WebWhoisProtocol {} + public @interface WebWhoisProtocol { + + } - /** {@link Provides} standard WebWhois sequence. */ + /** + * {@link Provides} standard WebWhois sequence. + */ @Provides @Singleton @IntoSet @@ -75,7 +93,9 @@ ProbingSequence provideWebWhoisSequence( } - /** {@link Provides} only step used in WebWhois sequence. */ + /** + * {@link Provides} only step used in WebWhois sequence. + */ @Provides @WebWhoisProtocol static ProbingStep provideWebWhoisStep( @@ -92,7 +112,9 @@ static ProbingStep provideWebWhoisStep( .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ + /** + * {@link Provides} the {@link Protocol} that corresponds to http connection. + */ @Singleton @Provides @HttpWhoisProtocol @@ -107,7 +129,9 @@ static Protocol provideHttpWhoisProtocol( .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ + /** + * {@link Provides} the {@link Protocol} that corresponds to https connection. + */ @Singleton @Provides @HttpsWhoisProtocol @@ -123,7 +147,10 @@ static Protocol provideHttpsWhoisProtocol( } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ + /** + * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http + * protocol. + */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( @@ -138,11 +165,15 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ + /** + * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https + * protocol. + */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( - @HttpsWhoisProtocol Provider> sslClientInitializerProvider, + @HttpsWhoisProtocol + Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, Provider messageHandlerProvider, @@ -165,20 +196,25 @@ static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int ma return new HttpObjectAggregator(maxContentLength); } - /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + /** + * {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. + */ @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + static SslClientInitializer provideSslClientInitializer( + SslProvider sslProvider) { return new SslClientInitializer<>(sslProvider); } - /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + /** + * {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. + */ @Singleton @Provides @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClazz){ + Class channelClazz) { return new Bootstrap() .group(eventLoopGroup) .channel(channelClazz); @@ -190,12 +226,14 @@ int provideMaximumMessageLengthBytes() { return maximumMessageLengthBytes; } - /** {@link Provides} the list of top level domains to be probed */ + /** + * {@link Provides} the list of top level domains to be probed + */ @Singleton @Provides @WebWhoisProtocol ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); + return ImmutableList.of("how", "soy", "xn--q9jyb4c"); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index adb833ec629..776a231d6dd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,8 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when - * the action performed failed due to an issue in the connection with the server. + * Subclass of {@link UndeterminedStateException} that represents all instances when the action + * performed failed due to an issue in the connection with the server. */ public class ConnectionException extends UndeterminedStateException { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java index c155d695c7f..d7127717d52 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java @@ -15,9 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails - * before we can determine the state of the result, meaning the status - * is recorded as ERROR. + * Base exception class for all instances when the action performed fails before we can determine + * the state of the result, meaning the status is recorded as ERROR. */ public class UndeterminedStateException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 6b6dad914a4..6552bca3eca 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -16,28 +16,30 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; /** - *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline + * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType + * >}, as it should only be passed in messages that implement the {@link InboundMessageType} + * interface.

* - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error. If the error is an instance of a {@link FailureException} {@code finished} is - * marked as a failure with cause {@link FailureException}. If it is any other type of error, it - * is treated as an {@link UndeterminedStateException} and {@code finished} set as a failure with - * the same cause as what caused the exception. Lastly, if no error is thrown, we know the action - * completed as a success, and, as such, we mark {@code finished} as a success.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a + * {@link + * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this + * channel is informed of the error. If the error is an instance of a {@link FailureException} + * {@code finished} is marked as a failure with cause {@link FailureException}. If it is any other + * type of error, it is treated as an {@link UndeterminedStateException} and {@code finished} set as + * a failure with the same cause as what caused the exception. Lastly, if no error is thrown, we + * know the action completed as a success, and, as such, we mark {@code finished} as a success.

* *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ @@ -45,22 +47,30 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler privateKeySupplier, Supplier certificateSupplier) { + public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, + Supplier certificateSupplier) { //We use the default trust store here as well, setting trustCertificates to null this(sslProvider, null, privateKeySupplier, certificateSupplier); } @@ -99,8 +98,10 @@ protected void initChannel(C channel) throws Exception { SslContextBuilder.forClient() .sslProvider(sslProvider) .trustManager(trustedCertificates); - if (privateKeySupplier != null && certificateSupplier != null) - sslContextBuilder = sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get()); + if (privateKeySupplier != null && certificateSupplier != null) { + sslContextBuilder = sslContextBuilder + .keyManager(privateKeySupplier.get(), certificateSupplier.get()); + } SslHandler sslHandler = sslContextBuilder .build() diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index de20c6b9269..c0f7ce8ae78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,17 +14,15 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; @@ -38,10 +36,11 @@ import org.joda.time.Duration; /** - *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection - * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

+ *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response + * implies a redirection it follows the redirection until either an Error Response is received, or + * {@link HttpResponseStatus.OK} is received

*/ public class WebWhoisActionHandler extends ActionHandler { @@ -49,16 +48,24 @@ public class WebWhoisActionHandler extends ActionHandler { /** Dagger injected components necessary for redirect responses: */ - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + /** + * {@link Bootstrap} necessary for remaking connection on redirect response. + */ private final Bootstrap bootstrap; - /** {@link Protocol} for when redirected to http endpoint. */ + /** + * {@link Protocol} for when redirected to http endpoint. + */ private final Protocol httpWhoisProtocol; - /** {@link Protocol} for when redirected to https endpoint. */ + /** + * {@link Protocol} for when redirected to https endpoint. + */ private final Protocol httpsWhoisProtocol; - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + /** + * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. + */ private final HttpRequestMessage requestMessage; @Inject @@ -76,9 +83,10 @@ public WebWhoisActionHandler( /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, + * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a + * response indicating a Failure, or receives a redirection response, where it follows the + * redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) @@ -101,13 +109,17 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException( + "Redirected Location was invalid. Given Location was: " + response.headers() + .get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, url.getDefaultPort(), newPath)); + logger.atInfo().log(String + .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, + url.getDefaultPort(), newPath)); //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; @@ -116,7 +128,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new FailureException("Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); + throw new FailureException( + "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -141,10 +154,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atWarning().log("Channel was unsuccessfully closed."); } - //Once channel is closed, establish new connection to redirected host, and repeat same actions + //Once channel is closed, establish new connection to redirected host, and repeat + // same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + //Once we have a successful call, set original ChannelPromise as success to tell + // ProbingStep we can move on secondFuture.addListener(f2 -> { if (f2.isSuccess()) { super.channelRead0(ctx, msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 58c395ad86e..576d6a04d42 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -24,25 +24,32 @@ import javax.inject.Inject; /** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} - * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection. + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom + * type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for + * redirection. */ public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject - public WebWhoisMessageHandler() {} + public WebWhoisMessageHandler() { + } - /** Retains {@link HttpRequestMessage} and calls super write method. */ + /** + * Retains {@link HttpRequestMessage} and calls super write method. + */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) + throws Exception { HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ + /** + * Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link + * InboundMessageType} instance. + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8d285811e0d..92e43501438 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -26,8 +26,8 @@ * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. * *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

+ * that modifies the request to reflect the new host and optional path. We also implement a {@code + * name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { @@ -39,7 +39,9 @@ public HttpRequestMessage() { private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, + ByteBuf content) { super(httpVersion, method, uri, content); } @@ -50,19 +52,24 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ + /** + * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} + */ public HttpRequestMessage(FullHttpRequest request) { this(request.protocolVersion(), request.method(), request.uri(), request.content()); request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } - /** Modifies headers to reflect new host and new path if applicable. */ + /** + * Modifies headers to reflect new host and new path if applicable. + */ @Override public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { if (args.length == 1 || args.length == 2) { headers().set("host", args[0]); - if (args.length == 2) + if (args.length == 2) { setUri(args[1]); + } return this; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index f1b2d6ac6a7..7d2ff722076 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -29,8 +29,10 @@ private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, Byte super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { + /** + * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} + */ + public HttpResponseMessage(FullHttpResponse response) { this(response.protocolVersion(), response.status(), response.content()); response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 578526933ba..1d686e4ec34 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -17,4 +17,6 @@ /** * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ -public interface InboundMessageType {} +public interface InboundMessageType { + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 6e3da3f69d2..e435ae59f86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -21,10 +21,16 @@ */ public interface OutboundMessageType { - /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + /** + * All {@link OutboundMessageType} implementing classes should be able to be modified by token + * with String arguments + */ OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; - /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + /** + * Necessary to inform metrics collector what kind of message is sent down {@link + * io.netty.channel.ChannelPipeline} + */ @Override String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dab5851e8d8..b10c45dae8a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,19 +14,19 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.ProbingSequence; import google.registry.monitoring.blackbox.ProbingStep; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} - * in a single loop of a {@link ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} in a single loop of a + * {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes - * on channel that remains unchanged within a loop of the sequence.

+ * in a {@link ProbingSequence}. Additionally, passes on channel that remains unchanged within a + * loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop * in the sequence.

@@ -34,27 +34,38 @@ public abstract class Token { /** - * {@link Channel} that always starts out as null. Once a persistent connection - * is made (such as EPP), that channel is stored in the token and passed on to - * later steps in the sequence until a new loop begins. + * {@link Channel} that always starts out as null. Once a persistent connection is made (such as + * EPP), that channel is stored in the token and passed on to later steps in the sequence until a + * new loop begins. */ protected Channel channel; - /** Obtains next {@link Token} for next loop in sequence. */ + /** + * Obtains next {@link Token} for next loop in sequence. + */ public abstract Token next(); - /** String corresponding to host that is relevant for loop in sequence. */ + /** + * String corresponding to host that is relevant for loop in sequence. + */ public abstract String host(); - /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; + /** + * Modifies the {@link OutboundMessageType} in the manner necessary for each loop + */ + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) + throws UndeterminedStateException; - /** Set method for {@code channel} */ + /** + * Set method for {@code channel} + */ public void setChannel(Channel channel) { this.channel = channel; } - /** Get method for {@code channel}. */ + /** + * Get method for {@code channel}. + */ public Channel channel() { return this.channel; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index bb06ee89db6..3ff852f3556 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -19,26 +19,30 @@ import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import java.util.Iterator; -import java.util.LinkedList; import javax.inject.Inject; -import javax.inject.Named; /** * {@link Token} subtype designed for WebWhois sequence. * *

Between loops of a WebWhois sequence the only thing changing is the tld we - * are probing. As a result, we maintain the list of {@code topLevelDomains} and - * on each call to next, have our index looking at the next {@code topLevelDomain}.

+ * are probing. As a result, we maintain the list of {@code topLevelDomains} and on each call to + * next, have our index looking at the next {@code topLevelDomain}.

*/ public class WebWhoisToken extends Token { - /** For each top level domain (tld), we probe "prefix.tld". */ - private final static String PREFIX = "whois.nic."; + /** + * For each top level domain (tld), we probe "prefix.tld". + */ + private static final String PREFIX = "whois.nic."; - /** {@link ImmutableList} of all top level domains to be probed. */ + /** + * {@link ImmutableList} of all top level domains to be probed. + */ private final Iterator topLevelDomainsIterator; - /** Current index of {@code topLevelDomains} that represents tld we are probing. */ + /** + * Current index of {@code topLevelDomains} that represents tld we are probing. + */ private String currentDomain; @Inject @@ -48,20 +52,28 @@ public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { currentDomain = topLevelDomainsIterator.next(); } - /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ + /** + * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. + */ @Override public WebWhoisToken next() { currentDomain = topLevelDomainsIterator.next(); return this; } - /** Modifies message to reflect the new host coming from the new top level domain. */ + /** + * Modifies message to reflect the new host coming from the new top level domain. + */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + public OutboundMessageType modifyMessage(OutboundMessageType original) + throws UndeterminedStateException { return original.modifyMessage(host()); } - /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ + /** + * Returns host as the concatenation of fixed {@code prefix} and current value of {@code + * topLevelDomains}. + */ @Override public String host() { return PREFIX + currentDomain; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index f7857dd80f9..6cfb235d97c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -43,14 +43,16 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; + /** * Unit tests for {@link ProbingAction} subtypes * *

Attempts to test how well each {@link ProbingAction} works with an {@link ActionHandler} * subtype when receiving to all possible types of responses

- * */ + */ @RunWith(JUnit4.class) public class ProbingActionTest { + private static final String TEST_MESSAGE = "MESSAGE_TEST"; private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; @@ -59,14 +61,19 @@ public class ProbingActionTest { private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ + /** + * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on + * {@link ProbingAction} + */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); private Provider testHandlerProvider = () -> testHandler; private Provider conversionHandlerProvider = () -> conversionHandler; - /** Used for testing how well probing step can create connection to blackbox server */ + /** + * Used for testing how well probing step can create connection to blackbox server + */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); @@ -152,10 +159,10 @@ public void testSuccess_newChannel() throws Exception { //Tests to see if message is properly sent to remote server nettyRule.assertReceivedMessage(TEST_MESSAGE); - future.syncUninterruptibly(); + future = future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler) testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 1f09dd13553..307d19221dd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -48,29 +48,39 @@ import org.junit.Test; import org.mockito.Mockito; -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +/** + * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific + * implementations + */ public class ProbingStepTest { - /** Basic Constants necessary for tests */ - private final static String ADDRESS_NAME = "TEST_ADDRESS"; - private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final static int PROTOCOL_PORT = 0; - private final static String TEST_MESSAGE = "TEST_MESSAGE"; - private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + /** + * Basic Constants necessary for tests + */ + private static final String ADDRESS_NAME = "TEST_ADDRESS"; + private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private static final int PROTOCOL_PORT = 0; + private static final String TEST_MESSAGE = "TEST_MESSAGE"; + private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private static final LocalAddress ADDRESS = new LocalAddress(ADDRESS_NAME); private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); - /** Used for testing how well probing step can create connection to blackbox server */ + /** + * Used for testing how well probing step can create connection to blackbox server + */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + /** + * The two main handlers we need in any test pipeline used that connects to {@link NettyRule's + * server} + **/ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); @@ -119,7 +129,7 @@ public void testNewChannel() throws Exception { Token testToken = new NewChannelToken(ADDRESS_NAME); //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(address); + nettyRule.setUpServer(ADDRESS); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -179,7 +189,8 @@ public void testWithSequence_ExistingChannel() throws Exception { assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + //Call accept on the first step, which should send our message through the EmbeddedChannel + // pipeline firstStep.accept(testToken); Object msg = channel.readOutbound(); @@ -188,7 +199,7 @@ public void testWithSequence_ExistingChannel() throws Exception { msg = channel.readOutbound(); } //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + assertThat(((ByteBuf) channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java deleted file mode 100644 index 46615a506fb..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; - -import com.google.common.collect.ImmutableList; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; -import io.netty.channel.nio.NioEventLoopGroup; - -/** - * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform - */ -public abstract class TestServer { - - TestServer(LocalAddress localAddress, ImmutableList handlers) { - this(new NioEventLoopGroup(1), localAddress, handlers); - } - - TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - //Creates ChannelInitializer with handlers specified - ChannelInitializer serverInitializer = new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) { - for (ChannelHandler handler : handlers) { - ch.pipeline().addLast(handler); - } - } - }; - //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using LocalServerChannel class - ServerBootstrap serverBootstrap = - new ServerBootstrap() - .group(eventLoopGroup) - .channel(LocalServerChannel.class) - .childHandler(serverInitializer); - - ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java deleted file mode 100644 index 28b36190a7e..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; - -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandler.Sharable; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.local.LocalAddress; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpServerCodec; - -/** - * {@link TestServer} subtype that performs WebWhois Services Expected - * - *

It will either redirect the client to the correct location if given the - * requisite redirect input, give the client a successful response if they give - * the expected final destination, or give the client an error message if given - * an unexpected host location

- */ -public class WebWhoisServer extends TestServer { - - public WebWhoisServer(LocalAddress localAddress, ImmutableList handlers) { - super(localAddress, handlers); - } - - public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - super(eventLoopGroup, localAddress, handlers); - } - - /** Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the HttpRequestMessage object through pipeline */ - public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { - return new WebWhoisServer( - eventLoopGroup, - localAddress, - ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) - ); - } - /** Creates server that sends exactly what we expect a remote server to send as a response, by sending the {@link ByteBuf} of the response through pipeline */ - public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { - return new WebWhoisServer( - eventLoopGroup, - localAddress, - ImmutableList.of( - new HttpServerCodec(), - new HttpObjectAggregator(1048576), - new RedirectHandler(redirectInput, destinationInput)) - ); - } - - /** - * Handler that will wither redirect client, give successful response, or give error messge - */ - @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { - private String redirectInput; - private String destinationInput; - - /** - * - * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location - */ - public RedirectHandler(String redirectInput, String destinationInput) { - this.redirectInput = redirectInput; - this.destinationInput = destinationInput; - } - - /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ - @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { - HttpResponse response; - if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); - } else if (request.headers().get("host").equals(destinationInput)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); - } - ctx.channel().writeAndFlush(response); - - } - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 50c60d9fc52..c0c5831a68c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -29,7 +29,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** Utility class for various helper methods used in testing. */ +/** + * Utility class for various helper methods used in testing. + */ public class TestUtils { public static FullHttpRequest makeHttpGetRequest(String host, String path) { @@ -52,7 +54,9 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { return response; } - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + /** + * Creates HttpResponse given status, redirection location, and other necessary inputs + */ public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); @@ -66,13 +70,17 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** Basic outline for {@link Token} instances to be used in tests */ - static abstract class TestToken extends Token { + /** + * Basic outline for {@link Token} instances to be used in tests + */ + abstract static class TestToken extends Token { + protected String host; protected TestToken(String host) { this.host = host; } + @Override public Token next() { return this; @@ -90,29 +98,29 @@ public String host() { } - /** {@link TestToken} instance that creates new channel */ + /** + * {@link TestToken} instance that creates new channel + */ public static class NewChannelToken extends TestToken { + public NewChannelToken(String host) { super(host); } + @Override public Channel channel() { return null; } } - /** {@link TestToken} instance that passes in existing channel */ + /** + * {@link TestToken} instance that passes in existing channel + */ public static class ExistingChannelToken extends TestToken { - private Channel channel; - public ExistingChannelToken(Channel channel, String host) { super(host); this.channel = channel; } - @Override - public Channel channel() { - return channel; - } } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index c9d337d6ad8..987abbfd7dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -28,15 +28,17 @@ import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to - * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link + * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} + * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** Handles inbound conversion */ + /** + * Handles inbound conversion + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; @@ -44,7 +46,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception buf.release(); } - /** Handles outbound conversion */ + /** + * Handles outbound conversion + */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 86b54d9a07d..f51f8c8fd61 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -28,7 +28,7 @@ import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -52,23 +52,24 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest} + *

*/ public final class NettyRule extends ExternalResource { - // All I/O operations are done inside the single thread within this event loop group, which is // different from the main test thread. Therefore synchronizations are required to make sure that // certain I/O activities are finished when assertions are performed. public NettyRule() { eventLoopGroup = new NioEventLoopGroup(1); } + public NettyRule(EventLoopGroup e) { eventLoopGroup = e; } + private final EventLoopGroup eventLoopGroup; - private WebWhoisServer webWhoisServer; // Handler attached to server's channel to record the request received. private EchoHandler echoHandler; @@ -78,16 +79,20 @@ public NettyRule(EventLoopGroup e) { private Channel channel; - /** Sets up a server channel bound to the given local address. */ + /** + * Sets up a server channel bound to the given local address. + */ public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.builder().add(handlers).add(echoHandler).build()); } - /** Sets up a client channel connecting to the give local address. */ + /** + * Sets up a client channel connecting to the give local address. + */ void setUpClient( LocalAddress localAddress, Protocol protocol, @@ -121,7 +126,9 @@ private void checkReady() { checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); } - /** Test that custom setup to send message to current server sends right message */ + /** + * Test that custom setup to send message to current server sends right message + */ public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); @@ -130,9 +137,9 @@ public void assertReceivedMessage(String message) throws Exception { /** * Test that a message can go through, both inbound and outbound. * - *

The client writes the message to the server, which echos it back and saves the string in its - * promise. The client receives the echo and saves it in its promise. All these activities happens - * in the I/O thread, and this call itself returns immediately. + *

The client writes the message to the server, which echos it back and saves the string in + * its promise. The client receives the echo and saves it in its promise. All these activities + * happens in the I/O thread, and this call itself returns immediately. */ void assertThatMessagesWork() throws Exception { checkReady(); @@ -196,7 +203,9 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E } } - /** A handler that dumps its inbound message to a promise that can be inspected later. */ + /** + * A handler that dumps its inbound message to a promise that can be inspected later. + */ private static class DumpHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture responseFuture = new CompletableFuture<>(); @@ -217,7 +226,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception responseFuture.complete(response); } - /** Saves any inbound error into the failure cause of the promise. */ + /** + * Saves any inbound error into the failure cause of the promise. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 523fb228752..25e5608a100 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -62,10 +62,14 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - /** Fake host to test if the SSL engine gets the correct peer host. */ + /** + * Fake host to test if the SSL engine gets the correct peer host. + */ private static final String SSL_HOST = "www.example.tld"; - /** Fake port to test if the SSL engine gets the correct peer port. */ + /** + * Fake port to test if the SSL engine gets the correct peer port. + */ private static final int SSL_PORT = 12345; @Rule @@ -78,20 +82,24 @@ public class SslClientInitializerTest { @Parameters(name = "{0}") public static SslProvider[] data() { return OpenSsl.isAvailable() - ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[] {SslProvider.JDK}; + ? new SslProvider[]{SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[]{SslProvider.JDK}; } - /** Saves the SNI hostname received by the server, if sent by the client. */ + /** + * Saves the SNI hostname received by the server, if sent by the client. + */ private String sniHostReceived; - /** Fake protocol saved in channel attribute. */ - private final static Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + /** + * Fake protocol saved in channel attribute. + */ + private static final Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -166,7 +174,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); @@ -195,7 +203,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 95b06e623d1..19e608c97d2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -20,8 +20,8 @@ import io.netty.channel.ChannelHandlerContext; /** - * Concrete implementation of {@link ActionHandler} that does nothing different from - * parent class other than store and return the {@code inboundMessage} + * Concrete implementation of {@link ActionHandler} that does nothing different from parent class + * other than store and return the {@code inboundMessage} */ public class TestActionHandler extends ActionHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 33eb190a66a..5a0d0908724 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -17,17 +17,16 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; @@ -39,7 +38,6 @@ import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -54,15 +52,10 @@ public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; - private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; - private static final String HTTPS_REDIRECT = "https://"; - private static final String REDIRECT_HOST = "www.example.com"; - private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private static final Duration DEFAULT_DURATION = new Duration(0L); - private final Protocol STANDARD_PROTOCOL = Protocol.builder() + private final Protocol standardProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( null, null, null, null))) .setName("http") @@ -96,8 +89,8 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, - STANDARD_PROTOCOL, - STANDARD_PROTOCOL, + standardProtocol, + standardProtocol, messageTemplate ); actionHandlerProvider = () -> actionHandler; @@ -177,6 +170,7 @@ public void testBasic_responseFailure_badRequest() { assertThat(future.cause() instanceof FailureException).isTrue(); } + @SuppressWarnings("CheckReturnValue") @Test public void testBasic_responseFailure_badURL() { //setup diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index bf5cfc45652..9a3e755364b 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -19,8 +19,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; From 5d998688f3bb0f6da99bdf3062f46cfc13f83fa9 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 20 Jun 2019 16:41:30 -0400 Subject: [PATCH 142/337] Initial Commit. --- .../monitoring/blackbox/ActionHandler.java | 5 + .../monitoring/blackbox/ProbingAction.java | 5 + .../monitoring/blackbox/ProbingSequence.java | 5 + .../monitoring/blackbox/ProbingStep.java | 5 + .../monitoring/blackbox/Protocol.java | 5 + .../monitoring/blackbox/TestToken.java | 5 + .../registry/monitoring/blackbox/Token.java | 5 + prober/build.gradle | 30 +- .../blackbox/AutoValue_NewChannelAction.java | 181 +++++++++++ .../blackbox/AutoValue_ProbingAction.java | 118 ++++++++ .../blackbox/AutoValue_Protocol.java | 153 ++++++++++ .../monitoring/blackbox/ActionHandler.java | 52 ++++ .../registry/monitoring/blackbox/Main.java | 8 + .../monitoring/blackbox/NewChannelAction.java | 70 +++++ .../monitoring/blackbox/ProbingAction.java | 285 ++++-------------- .../monitoring/blackbox/ProbingFlows.java | 15 + .../monitoring/blackbox/ProbingSequence.java | 86 +----- .../monitoring/blackbox/ProbingStep.java | 203 +++---------- .../monitoring/blackbox/Protocol.java | 59 ++-- .../monitoring/blackbox/TestToken.java | 28 ++ .../registry/monitoring/blackbox/Token.java | 20 ++ .../monitoring/blackbox/package-info.java | 16 + 22 files changed, 827 insertions(+), 532 deletions(-) create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Main.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/package-info.java diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java new file mode 100644 index 00000000000..a4d36657721 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ActionHandler { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java new file mode 100644 index 00000000000..6b26913d425 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingAction { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java new file mode 100644 index 00000000000..9f3617135a4 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingSequence { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java new file mode 100644 index 00000000000..b8b237a1e91 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingStep { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java new file mode 100644 index 00000000000..75d13b3039a --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class Protocol { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java new file mode 100644 index 00000000000..98f21f8d63a --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class TestToken { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java new file mode 100644 index 00000000000..16f05be0430 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class Token { + +} diff --git a/prober/build.gradle b/prober/build.gradle index 3652390d0ba..33feefb7175 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,30 +1,25 @@ -// Copyright 2019 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. - apply plugin: 'java' -createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') +createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Main') + dependencies { def deps = rootProject.dependencyMap + compile deps['com.beust:jcommander'] + compile deps['com.google.api-client:google-api-client'] + compile deps['com.google.apis:google-api-services-cloudkms'] + compile deps['com.google.apis:google-api-services-monitoring'] + compile deps['com.google.apis:google-api-services-storage'] compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] + compile deps['com.google.http-client:google-http-client'] + compile deps['com.google.monitoring-client:metrics'] + compile deps['com.google.monitoring-client:stackdriver'] compile deps['io.netty:netty-buffer'] compile deps['io.netty:netty-codec-http'] compile deps['io.netty:netty-codec'] @@ -41,10 +36,13 @@ dependencies { runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] + testCompile deps['com.google.monitoring-client:contrib'] testCompile deps['com.google.truth:truth'] + testCompile deps['org.yaml:snakeyaml'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') + testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -52,4 +50,4 @@ dependencies { testAnnotationProcessor deps['com.google.auto.value:auto-value'] annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] -} +} \ No newline at end of file diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java new file mode 100644 index 00000000000..6f818f03a28 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java @@ -0,0 +1,181 @@ + + +package google.registry.monitoring.blackbox; + +import io.netty.bootstrap.Bootstrap; +import javax.annotation.Generated; +import org.joda.time.Duration; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_NewChannelAction extends NewChannelAction { + + private final Duration delay; + + private final O outboundMessage; + + private final Protocol protocol; + + private final ActionHandler actionHandler; + + private final Bootstrap bootstrap; + + private AutoValue_NewChannelAction( + Duration delay, + O outboundMessage, + Protocol protocol, + ActionHandler actionHandler, + Bootstrap bootstrap) { + this.delay = delay; + this.outboundMessage = outboundMessage; + this.protocol = protocol; + this.actionHandler = actionHandler; + this.bootstrap = bootstrap; + } + + @Override + Duration delay() { + return delay; + } + + @Override + O outboundMessage() { + return outboundMessage; + } + + @Override + Protocol protocol() { + return protocol; + } + + @Override + ActionHandler actionHandler() { + return actionHandler; + } + + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + @Override + public String toString() { + return "NewChannelAction{" + + "delay=" + delay + ", " + + "outboundMessage=" + outboundMessage + ", " + + "protocol=" + protocol + ", " + + "actionHandler=" + actionHandler + ", " + + "bootstrap=" + bootstrap + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof NewChannelAction) { + NewChannelAction that = (NewChannelAction) o; + return this.delay.equals(that.delay()) + && this.outboundMessage.equals(that.outboundMessage()) + && this.protocol.equals(that.protocol()) + && this.actionHandler.equals(that.actionHandler()) + && this.bootstrap.equals(that.bootstrap()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= delay.hashCode(); + h$ *= 1000003; + h$ ^= outboundMessage.hashCode(); + h$ *= 1000003; + h$ ^= protocol.hashCode(); + h$ *= 1000003; + h$ ^= actionHandler.hashCode(); + h$ *= 1000003; + h$ ^= bootstrap.hashCode(); + return h$; + } + + static final class Builder extends NewChannelAction.Builder { + private Duration delay; + private O outboundMessage; + private Protocol protocol; + private ActionHandler actionHandler; + private Bootstrap bootstrap; + Builder() { + } + @Override + public NewChannelAction.Builder delay(Duration delay) { + if (delay == null) { + throw new NullPointerException("Null delay"); + } + this.delay = delay; + return this; + } + @Override + public NewChannelAction.Builder outboundMessage(O outboundMessage) { + if (outboundMessage == null) { + throw new NullPointerException("Null outboundMessage"); + } + this.outboundMessage = outboundMessage; + return this; + } + @Override + public NewChannelAction.Builder protocol(Protocol protocol) { + if (protocol == null) { + throw new NullPointerException("Null protocol"); + } + this.protocol = protocol; + return this; + } + @Override + public NewChannelAction.Builder actionHandler(ActionHandler actionHandler) { + if (actionHandler == null) { + throw new NullPointerException("Null actionHandler"); + } + this.actionHandler = actionHandler; + return this; + } + @Override + public NewChannelAction.Builder bootstrap(Bootstrap bootstrap) { + if (bootstrap == null) { + throw new NullPointerException("Null bootstrap"); + } + this.bootstrap = bootstrap; + return this; + } + @Override + public NewChannelAction build() { + String missing = ""; + if (this.delay == null) { + missing += " delay"; + } + if (this.outboundMessage == null) { + missing += " outboundMessage"; + } + if (this.protocol == null) { + missing += " protocol"; + } + if (this.actionHandler == null) { + missing += " actionHandler"; + } + if (this.bootstrap == null) { + missing += " bootstrap"; + } + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing required properties:" + missing); + } + return new AutoValue_NewChannelAction( + this.delay, + this.outboundMessage, + this.protocol, + this.actionHandler, + this.bootstrap); + } + } + +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java new file mode 100644 index 00000000000..26f560b145b --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java @@ -0,0 +1,118 @@ + + +package google.registry.monitoring.blackbox; + +import io.netty.channel.Channel; +import javax.annotation.Generated; +import org.joda.time.Duration; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_ProbingAction extends ProbingAction { + + private final Duration delay; + + private final O outboundMessage; + + private final Channel channel; + + private final Protocol protocol; + + private final ActionHandler actionHandler; + + AutoValue_ProbingAction( + Duration delay, + O outboundMessage, + Channel channel, + Protocol protocol, + ActionHandler actionHandler) { + if (delay == null) { + throw new NullPointerException("Null delay"); + } + this.delay = delay; + if (outboundMessage == null) { + throw new NullPointerException("Null outboundMessage"); + } + this.outboundMessage = outboundMessage; + if (channel == null) { + throw new NullPointerException("Null channel"); + } + this.channel = channel; + if (protocol == null) { + throw new NullPointerException("Null protocol"); + } + this.protocol = protocol; + if (actionHandler == null) { + throw new NullPointerException("Null actionHandler"); + } + this.actionHandler = actionHandler; + } + + @Override + Duration delay() { + return delay; + } + + @Override + O outboundMessage() { + return outboundMessage; + } + + @Override + Channel channel() { + return channel; + } + + @Override + Protocol protocol() { + return protocol; + } + + @Override + ActionHandler actionHandler() { + return actionHandler; + } + + @Override + public String toString() { + return "ProbingAction{" + + "delay=" + delay + ", " + + "outboundMessage=" + outboundMessage + ", " + + "channel=" + channel + ", " + + "protocol=" + protocol + ", " + + "actionHandler=" + actionHandler + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof ProbingAction) { + ProbingAction that = (ProbingAction) o; + return this.delay.equals(that.delay()) + && this.outboundMessage.equals(that.outboundMessage()) + && this.channel.equals(that.channel()) + && this.protocol.equals(that.protocol()) + && this.actionHandler.equals(that.actionHandler()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= delay.hashCode(); + h$ *= 1000003; + h$ ^= outboundMessage.hashCode(); + h$ *= 1000003; + h$ ^= channel.hashCode(); + h$ *= 1000003; + h$ ^= protocol.hashCode(); + h$ *= 1000003; + h$ ^= actionHandler.hashCode(); + return h$; + } + +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java new file mode 100644 index 00000000000..3247cbdd310 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java @@ -0,0 +1,153 @@ + + +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_Protocol extends Protocol { + + private final String name; + + private final int port; + + private final String host; + + private final ImmutableList> handlerProviders; + + private AutoValue_Protocol( + String name, + int port, + String host, + ImmutableList> handlerProviders) { + this.name = name; + this.port = port; + this.host = host; + this.handlerProviders = handlerProviders; + } + + @Override + String name() { + return name; + } + + @Override + int port() { + return port; + } + + @Override + String host() { + return host; + } + + @Override + ImmutableList> handlerProviders() { + return handlerProviders; + } + + @Override + public String toString() { + return "Protocol{" + + "name=" + name + ", " + + "port=" + port + ", " + + "host=" + host + ", " + + "handlerProviders=" + handlerProviders + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Protocol) { + Protocol that = (Protocol) o; + return this.name.equals(that.name()) + && this.port == that.port() + && this.host.equals(that.host()) + && this.handlerProviders.equals(that.handlerProviders()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= name.hashCode(); + h$ *= 1000003; + h$ ^= port; + h$ *= 1000003; + h$ ^= host.hashCode(); + h$ *= 1000003; + h$ ^= handlerProviders.hashCode(); + return h$; + } + + static final class Builder extends Protocol.Builder { + private String name; + private Integer port; + private String host; + private ImmutableList> handlerProviders; + Builder() { + } + @Override + Protocol.Builder name(String name) { + if (name == null) { + throw new NullPointerException("Null name"); + } + this.name = name; + return this; + } + @Override + Protocol.Builder port(int port) { + this.port = port; + return this; + } + @Override + Protocol.Builder host(String host) { + if (host == null) { + throw new NullPointerException("Null host"); + } + this.host = host; + return this; + } + @Override + Protocol.Builder handlerProviders(ImmutableList> handlerProviders) { + if (handlerProviders == null) { + throw new NullPointerException("Null handlerProviders"); + } + this.handlerProviders = handlerProviders; + return this; + } + @Override + Protocol build() { + String missing = ""; + if (this.name == null) { + missing += " name"; + } + if (this.port == null) { + missing += " port"; + } + if (this.host == null) { + missing += " host"; + } + if (this.handlerProviders == null) { + missing += " handlerProviders"; + } + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing required properties:" + missing); + } + return new AutoValue_Protocol( + this.name, + this.port, + this.host, + this.handlerProviders); + } + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java new file mode 100644 index 00000000000..1437d600539 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -0,0 +1,52 @@ +// 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.monitoring.blackbox; + +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import java.util.function.Function; + +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { + + private ChannelPromise finished; + private Channel channel; + + @Override + public ChannelFuture apply(O outboundMessage) { + // Send the request to server. + channel.writeAndFlush(outboundMessage); + return finished; + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) { + channel = ctx.channel(); + finished = ctx.newPromise(); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, I InboundMessage) { + // Response received, validate it, register metrics, etc. + // Once everything is done, mark the promise as success; + + finished.setSuccess(); + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java new file mode 100644 index 00000000000..61699ce033c --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java @@ -0,0 +1,8 @@ +package google.registry.monitoring.blackbox; + +public class Main { + public static void main(String[] args) { + System.out.println("Hello, world!"); + + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..ce452e19bf0 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,70 @@ +package google.registry.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOutboundInvoker; +import io.netty.channel.ChannelPromise; +import io.netty.channel.DefaultChannelPromise; +import io.netty.channel.socket.nio.NioSocketChannel; +import org.joda.time.Duration; + +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + abstract Bootstrap bootstrap(); + + private Channel channel; + + @Override + public Channel channel() { + return this.channel; + } + + @Override + public ChannelFuture call() { + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(NioSocketChannel outboundChannel) + throws Exception { + addHandlers( + outboundChannel.pipeline(), protocol().handlerProviders()); + } + }); + + ChannelFuture connectionFuture = bootstrap.connect(protocol().host(), protocol().port()); + ChannelPromise finished = null; + + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + this.channel = channelFuture.channel(); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + + } + } + ); + return finished; + } + + public static ProbingAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder(); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder outboundMessage(O value); + + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index cdb099e4a76..2ccf818a57a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,288 +14,104 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; -import io.netty.util.AttributeKey; import io.netty.util.HashedWheelTimer; import io.netty.util.Timer; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import javax.inject.Provider; -import org.joda.time.Duration; /** - * AutoValue class that represents action generated by {@link ProbingStep} + *Class that represents given action in sequence of probing * - *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when - * the task has been completed

- * - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type - * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall - * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the - * details of that connection.

- * - *

In its build, if there is no channel supplied, it will create a channel from the attributes - * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when - * informed that the connection is successful. If the channel is supplied, the connection future is - * automatically set to successful.

*/ -@AutoValue -public abstract class ProbingAction implements Callable { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** - * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when - * channel is active. - */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey - .valueOf("CONNECTION_FUTURE_KEY"); +public abstract class ProbingAction implements Callable { /** - * {@link AttributeKey} in channel that gives the information of the channel's host. - */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey - .valueOf("REMOTE_ADDRESS_KEY"); - - /** - * {@link Timer} that rate limits probing + * timer that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); /** - * Actual {@link Duration} of this delay + * @return actual Duration of delay */ - public abstract Duration delay(); + abstract Duration delay(); /** - * {@link OutboundMessageType} instance that we write and flush down pipeline to server + * @return message to send to server */ - public abstract OutboundMessageType outboundMessage(); + abstract O outboundMessage(); /** - * {@link Channel} object that either created by or passed into this {@link ProbingAction} - * instance + * @return Channel object that represents connection between prober client and server */ - @Nullable - public abstract Channel channel(); + abstract Channel channel(); /** - * The {@link Protocol} instance that specifies type of connection + * @return The Protocol instance that represents action to be tested by this part in sequences */ - public abstract Protocol protocol(); + abstract Protocol protocol(); /** - * The hostname of the remote host we have a connection or will make a connection to + * @return The requisite instance of Action Handler, which is always the last Handler in the pipeline */ - public abstract String host(); + abstract Bootstrap bootstrap(); + abstract ActionHandler actionHandler(); /** - * Performs the work of the actual action - * - *

First, checks if channel is active by setting a listener to perform the bulk of the work - * when the connection future is successful.

- * - *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

* - *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

- * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. + * @return Builder for the ProbingAction Class */ - /** - * Method that calls on {@code performAction} when it is certain channel connection is - * established. + * The method that calls the ActionHandler to send a message down the channel pipeline + * @return future that denotes when the action has been successfully performed */ @Override public ChannelFuture call() { - //ChannelPromise that we return - ChannelPromise finished = channel().newPromise(); - - //Ensures channel has been set up with connection future as an attribute - checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); - - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture connectionFuture) -> { - if (connectionFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - - ActionHandler actionHandler; - try { - actionHandler = channel().pipeline().get(ActionHandler.class); - } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw - // an UndeterminedStateException - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); - - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture unusedFutureWriteAndFlush = - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> { - if (future.isSuccess()) { - ChannelFuture unusedFuture = finished.setSuccess(); - } else { - ChannelFuture unusedFuture = finished.setFailure(future.cause()); - } - }, - //If we don't have a persistent connection, close the connection to this - // channel - future -> { - if (!protocol().persistentConnection()) { + // Add the Handlers from the run the action + // (with delay if present), and remove the ActionHandler afterwards, + // in case the channel is to be reused later. - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) { - logger.atInfo() - .log("Closed stale channel. Moving on to next ProbingStep"); - } else { - logger.atWarning() - .log( - "Could not close channel. Stale connection still exists" - + "."); - } - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(connectionFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); + ChannelPromise finished = channel().newPromise(); + timer.newTimeout(timeout -> + // Retry logic may also be added here. + actionHandler().apply(outboundMessage()).addListeners( + future -> finished.setSuccess()), + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } + abstract static class Builder, P extends ProbingAction> { - /** - * {@link AutoValue.Builder} that does work of creating connection when not already present. - */ - @AutoValue.Builder - public abstract static class Builder { - - private Bootstrap bootstrap; - - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } - - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setHost(String value); - - public abstract Builder setChannel(Channel channel); - - abstract Protocol protocol(); - - abstract Channel channel(); + public abstract B delay(Duration value); - abstract String host(); + public abstract B outboundMessage(O value); - abstract ProbingAction autoBuild(); + public abstract B protocol(Protocol value); - public ProbingAction build() { - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - address = new LocalAddress(host()); - } - - checkArgument(channel() == null ^ bootstrap == null, - "One and only one of bootstrap and channel must be supplied."); - //If a channel is supplied, nothing is needed to be done - - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel() == null) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); - - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } - - //now we can actually build the ProbingAction - return autoBuild(); - } - } + public abstract B actionHandler(ActionHandler value); - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); + public abstract P build(); } - /** - * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified - * * @param channelPipeline is pipeline associated with channel that we want to add handlers to * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - private static void addHandlers( + static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { @@ -304,17 +120,20 @@ private static void addHandlers( } - @Override - public final String toString() { - return String.format( - "ProbingAction with delay: %d\n" - + "outboundMessage: %s\n" - + "protocol: %s\n" - + "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); + + /** + * @param channelPipeline is pipeline associated with channel we want to remove handlers from + * removes all handlers from pipeline + */ + static void removeHandlers(ChannelPipeline channelPipeline) { + while (channelPipeline.first() != null) { + channelPipeline.removeFirst(); + } } + + + + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java new file mode 100644 index 00000000000..73dfd778d69 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox; + +public class ProbingFlows { + + public static void main(String[] args) { + ProbingSequence sequence = new ProbingSequence + .Builder() + .addStep(new ProbingStep()) + .build(); + + sequence.start(); + + + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 175cf4dcfa5..7c14d9f0bf0 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -1,72 +1,22 @@ -// Copyright 2019 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.monitoring.blackbox; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.EventLoopGroup; - -/** - * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. - * - * - *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} - * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one - * is the first repeated step.

- * - *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once - * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest - * of the work.

- */ -public class ProbingSequence { - +class ProbingSequence { private ProbingStep firstStep; - /** - * Each {@link ProbingSequence} requires a start token to begin running. - */ - private Token startToken; - public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + // create a new unique token; + Token token = new TestToken<>(); + firstStep.accept(token); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link - * Bootstrap}. + * Builder that sequentially adds steps */ - public static class Builder { - + static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - - private Token startToken; - public Builder(Token startToken) { - this.startToken = startToken; - } - - /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, built, and pointed to by - * the previous {@link ProbingStep} added. - */ public Builder addStep(ProbingStep step) { - if (currentStep == null) { firstStep = step; } else { @@ -75,34 +25,18 @@ public Builder addStep(ProbingStep step) { currentStep = step; return this; - } - /** - * We take special note of the first repeated step. - */ - public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; - return this; } - /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private - * constructor to create {@link ProbingSequence}. - */ public ProbingSequence build() { - if (firstRepeatedStep == null) { - firstRepeatedStep = firstStep; - } - - currentStep.nextStep(firstRepeatedStep); - currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + currentStep.nextStep(firstStep); + return new ProbingSequence(this.firstStep); } + } - private ProbingSequence(ProbingStep firstStep, Token startToken) { + private ProbingSequence(ProbingStep firstStep) { this.firstStep = firstStep; - this.startToken = startToken; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 98867c01220..2e2e3575d07 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -1,196 +1,61 @@ -// Copyright 2019 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.monitoring.blackbox; import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import java.util.function.Consumer; -import org.joda.time.Duration; - -/** - * {@link AutoValue} class that represents generator of actions performed at each step in {@link - * ProbingSequence}. - * - *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} - * instances. It then modifies these components on each loop iteration with the consumed {@link - * Token} and from that, generates a new {@link ProbingAction} to call.

- */ -@AutoValue -public abstract class ProbingStep implements Consumer { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * Necessary boolean to inform when to obtain next {@link Token} - */ - protected boolean isLastStep = false; - private ProbingStep nextStep; - - /** - * Time delay duration between actions. - */ - abstract Duration duration(); - - /** - * {@link Protocol} type for this step. - */ - abstract Protocol protocol(); - - /** - * {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. - */ - abstract OutboundMessageType messageTemplate(); - - /** - * {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation - * of new channels. - */ - abstract Bootstrap bootstrap(); - - - /** Default {@link AutoValue.Builder} for {@link ProbingStep}. */ - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setDuration(Duration value); - public abstract Builder setProtocol(Protocol value); - public abstract Builder setMessageTemplate(OutboundMessageType value); +public class ProbingStep implements Consumer> { - public abstract Builder setBootstrap(Bootstrap value); + private ProbingStep nextStep; - public abstract ProbingStep build(); - } - - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); - } - - void lastStep() { - isLastStep = true; - } - - void nextStep(ProbingStep step) { + public void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + public ProbingStep nextStep() { return this.nextStep; } - /** - * Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} - */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { - OutboundMessageType message = token.modifyMessage(messageTemplate()); - ProbingAction.Builder probingActionBuilder = ProbingAction.builder() - .setDelay(duration()) - .setProtocol(protocol()) - .setOutboundMessage(message) - .setHost(token.host()); - - if (token.channel() != null) { - probingActionBuilder.setChannel(token.channel()); - } else { - probingActionBuilder.setBootstrap(bootstrap()); - } - - return probingActionBuilder.build(); - } - /** - * On the last step, gets the next {@link Token}. Otherwise, uses the same one. - */ - private Token generateNextToken(Token token) { - return isLastStep ? token.next() : token; + private ProbingAction generateAction(Token token) { + // Construct a new ProbingAction and return it. + // The action is only used for one invocation + // and uses the UniqueToken provided in the argument, to + // populate fields in the action. The UniqueToken contains + // all the information needed to create an action, including + // for example the test domain name to be created/deleted and + // the channel to reuse (for ExistingChannelActions). + + return NewChannelAction.builder() + .protocol(token.protocol()) + .outboundMessage(token.message()) + .actionHandler(token.actionHandler()) + .delay(token.DEFAULT_DURATION) + .build(); + } + private Token generateNextToken(Token token) { + // Given the input token, we should be able to deduce what + // this the token for the following steps to use. If this + // step generates an action to create a domain, and the next + // one checks for its existence, the domain contained in the + // token should not change. If this is the last step in a loop + // on the other hand, the next token should contain a new + // domain name for the next loop. + return token.next(); - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the - * action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is completed is - * marked as a success, we note a success. Otherwise, if the cause of failure will either be a - * failure or error.

- */ - @Override - public void accept(Token token) { - ProbingAction currentAction; - //attempt to generate new action. On error, move on to next step - try { - currentAction = generateAction(token); - } catch (UndeterminedStateException e) { - logger.atWarning().withCause(e).log("Error in Action Generation"); - nextStep.accept(generateNextToken(token)); - return; - } - - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch (Exception e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; - } - - future.addListener(f -> { - if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success - logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - - } else { - //On a failed result, we log the failure and note either a failure or error - logger.atSevere().withCause(f.cause()).log("Did not result in future success"); - } - - if (protocol().persistentConnection()) { - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - } - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - - }); } @Override - public final String toString() { - return String.format("ProbingStep with Protocol: %s\n" - + "OutboundMessage: %s\n", - protocol(), - messageTemplate().getClass().getName()); + public void accept(Token token) { + ChannelFuture future = generateAction(token).call(); + future.addListener(f -> nextStep().accept(generateNextToken(token))); } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 676fd80d740..ca18213acf6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -16,63 +16,46 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; import javax.inject.Provider; -/** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. - */ @AutoValue public abstract class Protocol { + final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - /** - * {@link AttributeKey} that lets channel reference {@link Protocol} that created it. - */ - public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + /** Protocol name. */ + abstract String name(); - public abstract String name(); + /** Port to bind to at remote host*/ + abstract int port(); - public abstract int port(); + abstract String host(); - /** - * The {@link ChannelHandler} providers to use for the protocol, in order. - */ + /** The {@link ChannelHandler} providers to use for the protocol, in order. */ abstract ImmutableList> handlerProviders(); - /** - * Boolean that notes if connection associated with Protocol is persistent. - */ - abstract boolean persistentConnection(); - - public static Builder builder() { + static Protocol.Builder builder() { return new AutoValue_Protocol.Builder(); } - /** Default {@link AutoValue.Builder} for {@link Protocol}. */ + public static Protocol defaultImplementation(){ + return Protocol.builder().name("Default").port(8080).host("127.0.0.1").handlerProviders(ImmutableList.of()).build(); + } + @AutoValue.Builder - public abstract static class Builder { + public static abstract class Builder { - public abstract Builder setName(String value); + abstract Builder name(String value); - public abstract Builder setPort(int num); + abstract Builder host(String value); - public abstract Builder setHandlerProviders( - ImmutableList> providers); + abstract Builder port(int num); - public abstract Builder setPersistentConnection(boolean value); + abstract Builder handlerProviders(ImmutableList> providers); - public abstract Protocol build(); + abstract Protocol build(); } - @Override - public final String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); - } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java new file mode 100644 index 00000000000..0fc57f8967e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java @@ -0,0 +1,28 @@ +package google.registry.monitoring.blackbox; + + +public class TestToken extends Token { + @Override + public Protocol protocol(){ + return Protocol.defaultImplementation(); + } + + @Override + public Token next() { + return this; + } + + @Override + public O message() { + return (O) this.domainName; + } + + @Override + public ActionHandler actionHandler() { + return new ActionHandler(); + } + + public static TestToken generateNext() { + return new TestToken(); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java new file mode 100644 index 00000000000..c20ed770888 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java @@ -0,0 +1,20 @@ +package google.registry.monitoring.blackbox; + +import org.joda.time.Duration; + +abstract class Token { + public static final Duration DEFAULT_DURATION = new Duration(2000L); + protected String domainName; + + abstract Protocol protocol(); + abstract Token next(); + abstract O message(); + abstract ActionHandler actionHandler(); + + private static String newDomainName(String previousName) { + return String.format("prober-%d", System.currentTimeMillis()); + } + + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java new file mode 100644 index 00000000000..b3d22bfd24d --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java @@ -0,0 +1,16 @@ +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package google.registry.monitoring.blackbox; \ No newline at end of file From f482ab19a964228cacd1053558ee6992745ab5cd Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 21 Jun 2019 14:23:16 -0400 Subject: [PATCH 143/337] Deleted unfinished features. Added ActionHandler and its Unit Tests. --- .../monitoring/blackbox/ActionHandler.java | 31 +++- .../registry/monitoring/blackbox/Main.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 70 --------- .../monitoring/blackbox/ProbingAction.java | 139 ------------------ .../monitoring/blackbox/ProbingFlows.java | 15 -- .../monitoring/blackbox/ProbingSequence.java | 42 ------ .../monitoring/blackbox/ProbingStep.java | 61 -------- .../monitoring/blackbox/Protocol.java | 61 -------- .../monitoring/blackbox/TestToken.java | 28 ---- .../registry/monitoring/blackbox/Token.java | 20 --- .../blackbox/TestActionHandler.java | 84 +++++++++++ .../monitoring/blackbox/package-info.java | 16 ++ 12 files changed, 124 insertions(+), 444 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/package-info.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java index 1437d600539..92e89102eac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -20,33 +20,50 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import java.util.function.Function; +import javax.inject.Inject; -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { private ChannelPromise finished; private Channel channel; + @Inject + public ActionHandler() {} + @Override - public ChannelFuture apply(O outboundMessage) { - // Send the request to server. + public ChannelFuture apply(Object outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + channel.writeAndFlush(outboundMessage); return finished; } @Override public void handlerAdded(ChannelHandlerContext ctx) { + //Once handler is added to channel pipeline, initialize channel and future for this handler channel = ctx.channel(); finished = ctx.newPromise(); } @Override - protected void channelRead0(ChannelHandlerContext ctx, I InboundMessage) { - // Response received, validate it, register metrics, etc. - // Once everything is done, mark the promise as success; + protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { + //Only purpose of Handler is to mark future as a success finished.setSuccess(); } + /** + *Both methods are only used for testing + */ + + public Channel getChannel() { + return channel; + } + + public ChannelPromise getFinished() { + return finished; + } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java index 61699ce033c..c093b9274f8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java @@ -2,7 +2,6 @@ public class Main { public static void main(String[] args) { - System.out.println("Hello, world!"); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index ce452e19bf0..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,70 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOutboundInvoker; -import io.netty.channel.ChannelPromise; -import io.netty.channel.DefaultChannelPromise; -import io.netty.channel.socket.nio.NioSocketChannel; -import org.joda.time.Duration; - -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - abstract Bootstrap bootstrap(); - - private Channel channel; - - @Override - public Channel channel() { - return this.channel; - } - - @Override - public ChannelFuture call() { - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(NioSocketChannel outboundChannel) - throws Exception { - addHandlers( - outboundChannel.pipeline(), protocol().handlerProviders()); - } - }); - - ChannelFuture connectionFuture = bootstrap.connect(protocol().host(), protocol().port()); - ChannelPromise finished = null; - - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - this.channel = channelFuture.channel(); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - - } - } - ); - return finished; - } - - public static ProbingAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder(); - } - - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { - - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder outboundMessage(O value); - - } - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java deleted file mode 100644 index 2ccf818a57a..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ /dev/null @@ -1,139 +0,0 @@ -// 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.monitoring.blackbox; - - -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableList; -import io.netty.bootstrap.Bootstrap; -import java.util.concurrent.TimeUnit; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; -import javax.inject.Provider; - -/** - *Class that represents given action in sequence of probing - * - */ - - -public abstract class ProbingAction implements Callable { - - /** - * timer that rate limits probing - */ - private static final Timer timer = new HashedWheelTimer(); - - /** - * @return actual Duration of delay - */ - abstract Duration delay(); - - /** - * @return message to send to server - */ - abstract O outboundMessage(); - - /** - * @return Channel object that represents connection between prober client and server - */ - abstract Channel channel(); - - /** - * @return The Protocol instance that represents action to be tested by this part in sequences - */ - abstract Protocol protocol(); - - /** - * @return The requisite instance of Action Handler, which is always the last Handler in the pipeline - */ - abstract Bootstrap bootstrap(); - abstract ActionHandler actionHandler(); - - /** - * - * @return Builder for the ProbingAction Class - */ - - /** - * The method that calls the ActionHandler to send a message down the channel pipeline - * @return future that denotes when the action has been successfully performed - */ - @Override - public ChannelFuture call() { - // Add the Handlers from the run the action - // (with delay if present), and remove the ActionHandler afterwards, - // in case the channel is to be reused later. - - ChannelPromise finished = channel().newPromise(); - timer.newTimeout(timeout -> - // Retry logic may also be added here. - actionHandler().apply(outboundMessage()).addListeners( - future -> finished.setSuccess()), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - return finished; - } - - abstract static class Builder, P extends ProbingAction> { - - public abstract B delay(Duration value); - - public abstract B outboundMessage(O value); - - public abstract B protocol(Protocol value); - - public abstract B actionHandler(ActionHandler value); - - public abstract P build(); - } - /** - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified - */ - static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } - - - - /** - * @param channelPipeline is pipeline associated with channel we want to remove handlers from - * removes all handlers from pipeline - */ - static void removeHandlers(ChannelPipeline channelPipeline) { - while (channelPipeline.first() != null) { - channelPipeline.removeFirst(); - } - } - - - - -} - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java deleted file mode 100644 index 73dfd778d69..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java +++ /dev/null @@ -1,15 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingFlows { - - public static void main(String[] args) { - ProbingSequence sequence = new ProbingSequence - .Builder() - .addStep(new ProbingStep()) - .build(); - - sequence.start(); - - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java deleted file mode 100644 index 7c14d9f0bf0..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ /dev/null @@ -1,42 +0,0 @@ -package google.registry.monitoring.blackbox; - -class ProbingSequence { - private ProbingStep firstStep; - - public void start() { - // create a new unique token; - Token token = new TestToken<>(); - firstStep.accept(token); - } - - /** - * Builder that sequentially adds steps - */ - static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - - public Builder addStep(ProbingStep step) { - if (currentStep == null) { - firstStep = step; - } else { - currentStep.nextStep(step); - } - - currentStep = step; - return this; - - } - - public ProbingSequence build() { - currentStep.nextStep(firstStep); - return new ProbingSequence(this.firstStep); - } - - } - - private ProbingSequence(ProbingStep firstStep) { - this.firstStep = firstStep; - } -} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java deleted file mode 100644 index 2e2e3575d07..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ /dev/null @@ -1,61 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import java.util.function.Consumer; - - -public class ProbingStep implements Consumer> { - - private ProbingStep nextStep; - - public void nextStep(ProbingStep step) { - this.nextStep = step; - } - - public ProbingStep nextStep() { - return this.nextStep; - } - - - - private ProbingAction generateAction(Token token) { - // Construct a new ProbingAction and return it. - // The action is only used for one invocation - // and uses the UniqueToken provided in the argument, to - // populate fields in the action. The UniqueToken contains - // all the information needed to create an action, including - // for example the test domain name to be created/deleted and - // the channel to reuse (for ExistingChannelActions). - - return NewChannelAction.builder() - .protocol(token.protocol()) - .outboundMessage(token.message()) - .actionHandler(token.actionHandler()) - .delay(token.DEFAULT_DURATION) - .build(); - - } - private Token generateNextToken(Token token) { - // Given the input token, we should be able to deduce what - // this the token for the following steps to use. If this - // step generates an action to create a domain, and the next - // one checks for its existence, the domain contained in the - // token should not change. If this is the last step in a loop - // on the other hand, the next token should contain a new - // domain name for the next loop. - return token.next(); - - } - - @Override - public void accept(Token token) { - ChannelFuture future = generateAction(token).call(); - future.addListener(f -> nextStep().accept(generateNextToken(token))); - } - - -} - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java deleted file mode 100644 index ca18213acf6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ /dev/null @@ -1,61 +0,0 @@ -// 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableList; -import io.netty.util.AttributeKey; -import io.netty.channel.ChannelHandler; -import javax.inject.Provider; - -@AutoValue -public abstract class Protocol { - final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - - /** Protocol name. */ - abstract String name(); - - /** Port to bind to at remote host*/ - abstract int port(); - - abstract String host(); - - /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - abstract ImmutableList> handlerProviders(); - - static Protocol.Builder builder() { - return new AutoValue_Protocol.Builder(); - } - - public static Protocol defaultImplementation(){ - return Protocol.builder().name("Default").port(8080).host("127.0.0.1").handlerProviders(ImmutableList.of()).build(); - } - - @AutoValue.Builder - public static abstract class Builder { - - abstract Builder name(String value); - - abstract Builder host(String value); - - abstract Builder port(int num); - - abstract Builder handlerProviders(ImmutableList> providers); - - abstract Protocol build(); - } - - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java deleted file mode 100644 index 0fc57f8967e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java +++ /dev/null @@ -1,28 +0,0 @@ -package google.registry.monitoring.blackbox; - - -public class TestToken extends Token { - @Override - public Protocol protocol(){ - return Protocol.defaultImplementation(); - } - - @Override - public Token next() { - return this; - } - - @Override - public O message() { - return (O) this.domainName; - } - - @Override - public ActionHandler actionHandler() { - return new ActionHandler(); - } - - public static TestToken generateNext() { - return new TestToken(); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java deleted file mode 100644 index c20ed770888..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java +++ /dev/null @@ -1,20 +0,0 @@ -package google.registry.monitoring.blackbox; - -import org.joda.time.Duration; - -abstract class Token { - public static final Duration DEFAULT_DURATION = new Duration(2000L); - protected String domainName; - - abstract Protocol protocol(); - abstract Token next(); - abstract O message(); - abstract ActionHandler actionHandler(); - - private static String newDomainName(String previousName) { - return String.format("prober-%d", System.currentTimeMillis()); - } - - - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java new file mode 100644 index 00000000000..091fbbbf9a4 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java @@ -0,0 +1,84 @@ +// 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelPromise; +import io.netty.channel.embedded.EmbeddedChannel; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + + +/** Unit tests for {@link ActionHandler}. */ +@RunWith(JUnit4.class) +public class TestActionHandler { + + private final ActionHandler actionHandler = new ActionHandler(); + private EmbeddedChannel channel; + + @Before + public void setup() { + channel = new EmbeddedChannel(actionHandler); + } + + @Test + public void testHandler_Params() { + //initial check on Channel Activity + assertThat(channel.isActive()).isTrue(); + + + //Ensures channel Handler points to is right what + assertThat(actionHandler.getChannel()).isEqualTo(channel); + } + + @Test + public void testHandler_Behavior() { + //initial check on Channel Activity + assertThat(channel.isActive()).isTrue(); + + + ByteBuf outboundBuffer = Unpooled.copyInt(64); + + //Use ActionHandler's write method to check if the future returned is accurate + //and that it accurately writes out the inputBuffer + assertThat(actionHandler.apply(outboundBuffer)).isEqualTo(actionHandler.getFinished()); + assertThat(channel.outboundMessages().poll()).isEqualTo(outboundBuffer); + + //Creates Promise that is set to success when something changes on actionHandler's future + ChannelPromise testPromise = channel.newPromise(); + actionHandler.getFinished().addListener(f -> testPromise.setSuccess()); + + //Ensure that before reading inbound data, actionHandler's future stays inactive + assertThat(testPromise.isSuccess()).isFalse(); + + ByteBuf inputBuffer = Unpooled.copyInt(128); + + //Check that ActionHandler doesn't do anything to inbound Buffer + assertThat(channel.writeInbound(inputBuffer)).isFalse(); + + + //ensures that actionHandler's future's listener is active and that it is set to success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(actionHandler.getFinished().isSuccess()).isTrue(); + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java new file mode 100644 index 00000000000..b3d22bfd24d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java @@ -0,0 +1,16 @@ +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package google.registry.monitoring.blackbox; \ No newline at end of file From 5a7912ba8dbb6be4bf9073f8c32c9b48b520cb65 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 21 Jun 2019 14:45:36 -0400 Subject: [PATCH 144/337] Included prober subproject in settings.gradle --- settings.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings.gradle b/settings.gradle index 9b2d11de8da..0cd8f4dd707 100644 --- a/settings.gradle +++ b/settings.gradle @@ -36,3 +36,5 @@ include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' +include 'prober' + From 9837fd17bab893385722fa5620554a509b2d30e3 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 24 Jun 2019 12:18:55 -0400 Subject: [PATCH 145/337] Added Protocol Class and its Basic Unit Tests --- .../monitoring/blackbox/ActionHandler.java | 69 ------------ .../monitoring/blackbox/Protocol.java | 75 +++++++++++++ .../blackbox/handlers/ActionHandler.java | 100 +++++------------- .../monitoring/blackbox/TestProtocol.java | 70 ++++++++++++ 4 files changed, 173 insertions(+), 141 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java deleted file mode 100644 index 92e89102eac..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ /dev/null @@ -1,69 +0,0 @@ -// 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.monitoring.blackbox; - -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import java.util.function.Function; -import javax.inject.Inject; - -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { - - private ChannelPromise finished; - private Channel channel; - - @Inject - public ActionHandler() {} - - @Override - public ChannelFuture apply(Object outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline - - channel.writeAndFlush(outboundMessage); - return finished; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) { - //Once handler is added to channel pipeline, initialize channel and future for this handler - channel = ctx.channel(); - finished = ctx.newPromise(); - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { - //Only purpose of Handler is to mark future as a success - - finished.setSuccess(); - } - - /** - *Both methods are only used for testing - */ - - public Channel getChannel() { - return channel; - } - - public ChannelPromise getFinished() { - return finished; - } - -} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java new file mode 100644 index 00000000000..3ddecba5af7 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -0,0 +1,75 @@ +// 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; +import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; +import javax.inject.Provider; + +@AutoValue +public abstract class Protocol { + + /** + * Default names associated with each protocol + */ + final static String EPP_PROTOCOL_NAME = "EPP"; + final static String DNS_PROTOCOL_NAME = "DNS"; + final static String WHOIS_PROTOCOL_NAME = "WHOIS"; + final static String RDAP_PROTOCOL_NAME = "RDAP"; + + final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + public boolean PERSISTENT_CONNECTION = name() == EPP_PROTOCOL_NAME; + /** + * @return name of Protocol. + */ + abstract String name(); + + /** + * @return Port to bind to at remote host + */ + abstract int port(); + + /** + * @return hostname to connect to + */ + abstract String host(); + + /** The {@link ChannelHandler} providers to use for the protocol, in order. */ + abstract ImmutableList> handlerProviders(); + + /** Builds new Protocol from @AutoValue Builder implementation*/ + static Protocol.Builder builder() { + return new AutoValue_Protocol.Builder(); + } + + + @AutoValue.Builder + public static abstract class Builder { + + abstract Builder name(String value); + + abstract Builder host(String value); + + abstract Builder port(int num); + + abstract Builder handlerProviders(ImmutableList> providers); + + abstract Protocol build(); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 6552bca3eca..54c51749aaf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,100 +14,56 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; - -/** - * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline - * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType - * >}, as it should only be passed in messages that implement the {@link InboundMessageType} - * interface.

- * - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a - * {@link - * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this - * channel is informed of the error. If the error is an instance of a {@link FailureException} - * {@code finished} is marked as a failure with cause {@link FailureException}. If it is any other - * type of error, it is treated as an {@link UndeterminedStateException} and {@code finished} set as - * a failure with the same cause as what caused the exception. Lastly, if no error is thrown, we - * know the action completed as a success, and, as such, we mark {@code finished} as a success.

- * - *

Subclasses specify further work to be done for specific kinds of channel pipelines.

- */ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +import java.util.function.Function; +import javax.inject.Inject; - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { - /** - * {@link ChannelPromise} that informs {@link ProbingAction} if response has been received. - */ private ChannelPromise finished; + private Channel channel; - /** - * Returns initialized {@link ChannelPromise} to {@link ProbingAction}. - */ - public ChannelFuture getFinishedFuture() { + @Inject + public ActionHandler() {} + + @Override + public ChannelFuture apply(Object outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + + channel.writeAndFlush(outboundMessage); return finished; } - /** - * Initializes {@link ChannelPromise} - */ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler + channel = ctx.channel(); finished = ctx.newPromise(); } - /** - * Marks {@link ChannelPromise} as success - */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { + //Only purpose of Handler is to mark future as a success - ChannelFuture unusedFuture = finished.setSuccess(); + finished.setSuccess(); } /** - * Logs the channel and pipeline that caused error, closes channel, then informs {@link - * ProbingAction} listeners of error. + *Both methods are only used for testing */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atWarning().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); - - if (cause instanceof FailureException) { - //On FailureException, we know the response is a failure. - - //Since it wasn't a success, we still want to log to see what caused the FAILURE - logger.atInfo().log(cause.getMessage()); - - //As always, inform the ProbingStep that we successfully completed this action - ChannelFuture unusedFuture = finished.setFailure(cause); - } else { - //On UndeterminedStateException, we know the response type is an error. - - //Since it wasn't a success, we still log what caused the ERROR - logger.atWarning().log(cause.getMessage()); - ChannelFuture unusedFuture = finished.setFailure(cause); + public Channel getChannel() { + return channel; + } - //As this was an ERROR in performing the action, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } + public ChannelPromise getFinished() { + return finished; } + } + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java new file mode 100644 index 00000000000..8f35843cb4c --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java @@ -0,0 +1,70 @@ +package google.registry.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.TestModule.TestProtocolModule; +import google.registry.monitoring.blackbox.TestModule.TestComponent; +import com.google.common.collect.ImmutableList; +import io.netty.channel.ChannelHandler; +import javax.inject.Inject; +import javax.inject.Provider; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Basic unit test for Protocol Class + */ +@RunWith(JUnit4.class) +public class TestProtocol { + + /** + * Stores default values that constitute a Protocol + */ + private static final String HOST_NAME = "127.0.0.1"; + private static final int PORT_NUM = 0; + private static final String NAME = "Test"; + private static final ImmutableList> HANDLERS = ImmutableList.of(); + + /** + * Test Protocol that we build + */ + private Protocol protocol; + + /** + * + * @return Protocol implementation built using fields above + */ + static Protocol defaultImplementation() { + return Protocol.builder() + .host(HOST_NAME) + .port(PORT_NUM) + .name(NAME) + .handlerProviders(HANDLERS) + .build(); + } + + /** + * Stores default implementation into private protocol field + */ + private void basicProtocol() { + protocol = TestProtocol.defaultImplementation(); + } + + + /** + * Basic unit test that insures stored values in protocol are accurate + */ + @Test + public void testProtocolAttributes() { + basicProtocol(); + assertThat(protocol.host()).isEqualTo(HOST_NAME); + assertThat(protocol.port()).isEqualTo(PORT_NUM); + assertThat(protocol.name()).isEqualTo(NAME); + assertThat(protocol.handlerProviders()).isEqualTo(HANDLERS); + } + + + +} From e241adb8fe3ec9d8bd39ddb6aa4e07f1c8d194a6 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 28 Jun 2019 17:10:59 -0400 Subject: [PATCH 146/337] Added Changes Suggested by jianglai --- prober/build.gradle | 6 +- .../registry/monitoring/blackbox/Main.java | 7 -- .../monitoring/blackbox/Protocol.java | 71 +++++++++++++------ .../blackbox/handlers/ActionHandler.java | 49 ++++++++----- .../monitoring/blackbox/package-info.java | 1 - .../ActionHandlerTest.java} | 3 +- .../monitoring/blackbox/TestProtocol.java | 70 ------------------ .../monitoring/blackbox/package-info.java | 1 - 8 files changed, 86 insertions(+), 122 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Main.java rename prober/src/test/java/google/registry/monitoring/blackbox/{TestActionHandler.java => Handlers/ActionHandlerTest.java} (95%) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java diff --git a/prober/build.gradle b/prober/build.gradle index 33feefb7175..fe5e08a62f5 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'java' -createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Main') +createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') dependencies { @@ -30,7 +30,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] - compile project(':util') + //compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] @@ -42,7 +42,7 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - testCompile project(path: ':core', configuration: 'testRuntime') + //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java deleted file mode 100644 index c093b9274f8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java +++ /dev/null @@ -1,7 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Main { - public static void main(String[] args) { - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 3ddecba5af7..50a1d90a12c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -20,6 +20,11 @@ import io.netty.channel.ChannelHandler; import javax.inject.Provider; +/** + * Protocol Class packages all static variables necessary for a certain type of connection + * Both the host and the path can be changed for the same protocol + * Mainly packages the handlers necessary for the requisite channel pipeline + */ @AutoValue public abstract class Protocol { @@ -31,28 +36,49 @@ public abstract class Protocol { final static String WHOIS_PROTOCOL_NAME = "WHOIS"; final static String RDAP_PROTOCOL_NAME = "RDAP"; - final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - public boolean PERSISTENT_CONNECTION = name() == EPP_PROTOCOL_NAME; - /** - * @return name of Protocol. - */ - abstract String name(); + private String host; + private String path = ""; - /** - * @return Port to bind to at remote host - */ - abstract int port(); + /** Setter method for Protocol's host*/ + public Protocol host(String host) { + this.host = host; + return this; + } - /** - * @return hostname to connect to - */ - abstract String host(); + /** Getter method for Protocol's host*/ + public String host() { + return host; + } + + /** Setter method for Protocol's path*/ + public Protocol path(String path) { + this.path = path; + return this; + } + + /** Getter method for Protocol's path*/ + public String path() { + return path; + } + + /** If connection associated with Protocol is persistent, which is only EPP */ + public boolean persistentConnection() { + return name() == EPP_PROTOCOL_NAME; + } + + /** Protocol Name */ + public abstract String name(); + + /** Port to bind to at remote host */ + public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - abstract ImmutableList> handlerProviders(); + public abstract ImmutableList> handlerProviders(); + + + public abstract Builder toBuilder(); - /** Builds new Protocol from @AutoValue Builder implementation*/ - static Protocol.Builder builder() { + public static Protocol.Builder builder() { return new AutoValue_Protocol.Builder(); } @@ -60,16 +86,15 @@ static Protocol.Builder builder() { @AutoValue.Builder public static abstract class Builder { - abstract Builder name(String value); + public abstract Builder name(String value); - abstract Builder host(String value); + public abstract Builder port(int num); - abstract Builder port(int num); + public abstract Builder handlerProviders(ImmutableList> providers); - abstract Builder handlerProviders(ImmutableList> providers); - - abstract Protocol build(); + public abstract Protocol build(); } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 54c51749aaf..a4df56408b5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,56 +14,73 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.flogger.FluentLogger; +import com.google.common.flogger.StackSize; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.HttpResponse; import java.util.function.Function; import javax.inject.Inject; -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { +/** + * + * @param Generic Type of Inbound Message + * @param Generic Type of Outbound Message + * Abstract class that tells sends message down pipeline and + * and tells listeners to move on when the message is received. + */ +public abstract class ActionHandler extends SimpleChannelInboundHandler + implements Function { - private ChannelPromise finished; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + protected ChannelPromise finished; private Channel channel; - @Inject - public ActionHandler() {} + /** returns ChannelPromise for when inbound message is recieved + * a + * @param outboundMessage + * @return + */ @Override - public ChannelFuture apply(Object outboundMessage) { + public ChannelFuture apply(O outboundMessage) { // Sends request along Outbound Handlers on the Pipeline channel.writeAndFlush(outboundMessage); return finished; + + } + + public void resetFuture() { + finished = channel.newPromise(); } @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler + channel = ctx.channel(); finished = ctx.newPromise(); } @Override - protected void channelRead0(ChannelHandlerContext ctx, Object InboundMessage) { + public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ //Only purpose of Handler is to mark future as a success finished.setSuccess(); } - /** - *Both methods are only used for testing - */ - - public Channel getChannel() { - return channel; + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } - public ChannelPromise getFinished() { - return finished; - } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java index b3d22bfd24d..21c8764701c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java @@ -12,5 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -@javax.annotation.ParametersAreNonnullByDefault package google.registry.monitoring.blackbox; \ No newline at end of file diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java similarity index 95% rename from prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java rename to prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java index 091fbbbf9a4..01b93866b14 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java @@ -12,10 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.Handlers; import static com.google.common.truth.Truth.assertThat; +import google.registry.monitoring.blackbox.handlers.ActionHandler; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelPromise; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java deleted file mode 100644 index 8f35843cb4c..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java +++ /dev/null @@ -1,70 +0,0 @@ -package google.registry.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import google.registry.monitoring.blackbox.TestModule.TestProtocolModule; -import google.registry.monitoring.blackbox.TestModule.TestComponent; -import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; -import javax.inject.Inject; -import javax.inject.Provider; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Basic unit test for Protocol Class - */ -@RunWith(JUnit4.class) -public class TestProtocol { - - /** - * Stores default values that constitute a Protocol - */ - private static final String HOST_NAME = "127.0.0.1"; - private static final int PORT_NUM = 0; - private static final String NAME = "Test"; - private static final ImmutableList> HANDLERS = ImmutableList.of(); - - /** - * Test Protocol that we build - */ - private Protocol protocol; - - /** - * - * @return Protocol implementation built using fields above - */ - static Protocol defaultImplementation() { - return Protocol.builder() - .host(HOST_NAME) - .port(PORT_NUM) - .name(NAME) - .handlerProviders(HANDLERS) - .build(); - } - - /** - * Stores default implementation into private protocol field - */ - private void basicProtocol() { - protocol = TestProtocol.defaultImplementation(); - } - - - /** - * Basic unit test that insures stored values in protocol are accurate - */ - @Test - public void testProtocolAttributes() { - basicProtocol(); - assertThat(protocol.host()).isEqualTo(HOST_NAME); - assertThat(protocol.port()).isEqualTo(PORT_NUM); - assertThat(protocol.name()).isEqualTo(NAME); - assertThat(protocol.handlerProviders()).isEqualTo(HANDLERS); - } - - - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java index b3d22bfd24d..21c8764701c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java @@ -12,5 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -@javax.annotation.ParametersAreNonnullByDefault package google.registry.monitoring.blackbox; \ No newline at end of file From 3c2434e5fe2e119ad23b280856be12b3c38c9b3d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:06:18 -0400 Subject: [PATCH 147/337] Fixed Gitignore to take out AutoValue generated code --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 327b22fe2e7..199c4fe3979 100644 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,9 @@ nomulus.iws # Javascript output **/out/* +# AutoValue generated code +AutoValue_.*.java + ###################################################################### # Python Ignores From 665c4f248c56038475e3f5d4a6690945366f74ac Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:07:59 -0400 Subject: [PATCH 148/337] Removed AutoValue java files --- .../blackbox/AutoValue_NewChannelAction.java | 181 ------------------ .../blackbox/AutoValue_ProbingAction.java | 118 ------------ .../blackbox/AutoValue_Protocol.java | 153 --------------- 3 files changed, 452 deletions(-) delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java deleted file mode 100644 index 6f818f03a28..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java +++ /dev/null @@ -1,181 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import io.netty.bootstrap.Bootstrap; -import javax.annotation.Generated; -import org.joda.time.Duration; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_NewChannelAction extends NewChannelAction { - - private final Duration delay; - - private final O outboundMessage; - - private final Protocol protocol; - - private final ActionHandler actionHandler; - - private final Bootstrap bootstrap; - - private AutoValue_NewChannelAction( - Duration delay, - O outboundMessage, - Protocol protocol, - ActionHandler actionHandler, - Bootstrap bootstrap) { - this.delay = delay; - this.outboundMessage = outboundMessage; - this.protocol = protocol; - this.actionHandler = actionHandler; - this.bootstrap = bootstrap; - } - - @Override - Duration delay() { - return delay; - } - - @Override - O outboundMessage() { - return outboundMessage; - } - - @Override - Protocol protocol() { - return protocol; - } - - @Override - ActionHandler actionHandler() { - return actionHandler; - } - - @Override - Bootstrap bootstrap() { - return bootstrap; - } - - @Override - public String toString() { - return "NewChannelAction{" - + "delay=" + delay + ", " - + "outboundMessage=" + outboundMessage + ", " - + "protocol=" + protocol + ", " - + "actionHandler=" + actionHandler + ", " - + "bootstrap=" + bootstrap - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof NewChannelAction) { - NewChannelAction that = (NewChannelAction) o; - return this.delay.equals(that.delay()) - && this.outboundMessage.equals(that.outboundMessage()) - && this.protocol.equals(that.protocol()) - && this.actionHandler.equals(that.actionHandler()) - && this.bootstrap.equals(that.bootstrap()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= delay.hashCode(); - h$ *= 1000003; - h$ ^= outboundMessage.hashCode(); - h$ *= 1000003; - h$ ^= protocol.hashCode(); - h$ *= 1000003; - h$ ^= actionHandler.hashCode(); - h$ *= 1000003; - h$ ^= bootstrap.hashCode(); - return h$; - } - - static final class Builder extends NewChannelAction.Builder { - private Duration delay; - private O outboundMessage; - private Protocol protocol; - private ActionHandler actionHandler; - private Bootstrap bootstrap; - Builder() { - } - @Override - public NewChannelAction.Builder delay(Duration delay) { - if (delay == null) { - throw new NullPointerException("Null delay"); - } - this.delay = delay; - return this; - } - @Override - public NewChannelAction.Builder outboundMessage(O outboundMessage) { - if (outboundMessage == null) { - throw new NullPointerException("Null outboundMessage"); - } - this.outboundMessage = outboundMessage; - return this; - } - @Override - public NewChannelAction.Builder protocol(Protocol protocol) { - if (protocol == null) { - throw new NullPointerException("Null protocol"); - } - this.protocol = protocol; - return this; - } - @Override - public NewChannelAction.Builder actionHandler(ActionHandler actionHandler) { - if (actionHandler == null) { - throw new NullPointerException("Null actionHandler"); - } - this.actionHandler = actionHandler; - return this; - } - @Override - public NewChannelAction.Builder bootstrap(Bootstrap bootstrap) { - if (bootstrap == null) { - throw new NullPointerException("Null bootstrap"); - } - this.bootstrap = bootstrap; - return this; - } - @Override - public NewChannelAction build() { - String missing = ""; - if (this.delay == null) { - missing += " delay"; - } - if (this.outboundMessage == null) { - missing += " outboundMessage"; - } - if (this.protocol == null) { - missing += " protocol"; - } - if (this.actionHandler == null) { - missing += " actionHandler"; - } - if (this.bootstrap == null) { - missing += " bootstrap"; - } - if (!missing.isEmpty()) { - throw new IllegalStateException("Missing required properties:" + missing); - } - return new AutoValue_NewChannelAction( - this.delay, - this.outboundMessage, - this.protocol, - this.actionHandler, - this.bootstrap); - } - } - -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java deleted file mode 100644 index 26f560b145b..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java +++ /dev/null @@ -1,118 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import io.netty.channel.Channel; -import javax.annotation.Generated; -import org.joda.time.Duration; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_ProbingAction extends ProbingAction { - - private final Duration delay; - - private final O outboundMessage; - - private final Channel channel; - - private final Protocol protocol; - - private final ActionHandler actionHandler; - - AutoValue_ProbingAction( - Duration delay, - O outboundMessage, - Channel channel, - Protocol protocol, - ActionHandler actionHandler) { - if (delay == null) { - throw new NullPointerException("Null delay"); - } - this.delay = delay; - if (outboundMessage == null) { - throw new NullPointerException("Null outboundMessage"); - } - this.outboundMessage = outboundMessage; - if (channel == null) { - throw new NullPointerException("Null channel"); - } - this.channel = channel; - if (protocol == null) { - throw new NullPointerException("Null protocol"); - } - this.protocol = protocol; - if (actionHandler == null) { - throw new NullPointerException("Null actionHandler"); - } - this.actionHandler = actionHandler; - } - - @Override - Duration delay() { - return delay; - } - - @Override - O outboundMessage() { - return outboundMessage; - } - - @Override - Channel channel() { - return channel; - } - - @Override - Protocol protocol() { - return protocol; - } - - @Override - ActionHandler actionHandler() { - return actionHandler; - } - - @Override - public String toString() { - return "ProbingAction{" - + "delay=" + delay + ", " - + "outboundMessage=" + outboundMessage + ", " - + "channel=" + channel + ", " - + "protocol=" + protocol + ", " - + "actionHandler=" + actionHandler - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof ProbingAction) { - ProbingAction that = (ProbingAction) o; - return this.delay.equals(that.delay()) - && this.outboundMessage.equals(that.outboundMessage()) - && this.channel.equals(that.channel()) - && this.protocol.equals(that.protocol()) - && this.actionHandler.equals(that.actionHandler()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= delay.hashCode(); - h$ *= 1000003; - h$ ^= outboundMessage.hashCode(); - h$ *= 1000003; - h$ ^= channel.hashCode(); - h$ *= 1000003; - h$ ^= protocol.hashCode(); - h$ *= 1000003; - h$ ^= actionHandler.hashCode(); - return h$; - } - -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java deleted file mode 100644 index 3247cbdd310..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java +++ /dev/null @@ -1,153 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_Protocol extends Protocol { - - private final String name; - - private final int port; - - private final String host; - - private final ImmutableList> handlerProviders; - - private AutoValue_Protocol( - String name, - int port, - String host, - ImmutableList> handlerProviders) { - this.name = name; - this.port = port; - this.host = host; - this.handlerProviders = handlerProviders; - } - - @Override - String name() { - return name; - } - - @Override - int port() { - return port; - } - - @Override - String host() { - return host; - } - - @Override - ImmutableList> handlerProviders() { - return handlerProviders; - } - - @Override - public String toString() { - return "Protocol{" - + "name=" + name + ", " - + "port=" + port + ", " - + "host=" + host + ", " - + "handlerProviders=" + handlerProviders - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof Protocol) { - Protocol that = (Protocol) o; - return this.name.equals(that.name()) - && this.port == that.port() - && this.host.equals(that.host()) - && this.handlerProviders.equals(that.handlerProviders()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= name.hashCode(); - h$ *= 1000003; - h$ ^= port; - h$ *= 1000003; - h$ ^= host.hashCode(); - h$ *= 1000003; - h$ ^= handlerProviders.hashCode(); - return h$; - } - - static final class Builder extends Protocol.Builder { - private String name; - private Integer port; - private String host; - private ImmutableList> handlerProviders; - Builder() { - } - @Override - Protocol.Builder name(String name) { - if (name == null) { - throw new NullPointerException("Null name"); - } - this.name = name; - return this; - } - @Override - Protocol.Builder port(int port) { - this.port = port; - return this; - } - @Override - Protocol.Builder host(String host) { - if (host == null) { - throw new NullPointerException("Null host"); - } - this.host = host; - return this; - } - @Override - Protocol.Builder handlerProviders(ImmutableList> handlerProviders) { - if (handlerProviders == null) { - throw new NullPointerException("Null handlerProviders"); - } - this.handlerProviders = handlerProviders; - return this; - } - @Override - Protocol build() { - String missing = ""; - if (this.name == null) { - missing += " name"; - } - if (this.port == null) { - missing += " port"; - } - if (this.host == null) { - missing += " host"; - } - if (this.handlerProviders == null) { - missing += " handlerProviders"; - } - if (!missing.isEmpty()) { - throw new IllegalStateException("Missing required properties:" + missing); - } - return new AutoValue_Protocol( - this.name, - this.port, - this.host, - this.handlerProviders); - } - } - -} From 9d350374256fd4ef742424d94ccf0c4e4fcbf5d2 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:28:29 -0400 Subject: [PATCH 149/337] Added gitignore within prober --- .../blackbox/ActionHandler_Factory.java | 25 +++ .../DaggerProberModule_ProberComponent.java | 154 +++++++++++++++++ ...aggerWebWhoisModule_WebWhoisComponent.java | 119 ++++++++++++++ ...berModule_ProvideHttpWhoIsPortFactory.java | 29 ++++ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoIsPortFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 29 ++++ ...odule_ProvidePortToProtocolMapFactory.java | 42 +++++ .../blackbox/ProbingStepWeb_Factory.java | 30 ++++ .../blackbox/ProbingStep_Factory.java | 27 +++ .../blackbox/TestToken_Factory.java | 45 +++++ .../blackbox/TestToken_MembersInjector.java | 30 ++++ .../TokenModule_DomainNameFactory.java | 27 +++ .../TokenModule_ProvideTokenFactory.java | 35 ++++ .../blackbox/Token_MembersInjector.java | 31 ++++ .../Tokens/WebWhoisToken_Factory.java | 25 +++ .../WebWhoisModule_HttpWhoisHostFactory.java | 28 ++++ .../WebWhoisModule_HttpWhoisPathFactory.java | 28 ++++ .../WebWhoisModule_HttpWhoisPortFactory.java | 26 +++ .../WebWhoisModule_HttpsWhoisHostFactory.java | 29 ++++ .../WebWhoisModule_HttpsWhoisPathFactory.java | 29 ++++ .../WebWhoisModule_HttpsWhoisPortFactory.java | 26 +++ ...sModule_ProvideHttpClientCodecFactory.java | 31 ++++ ...le_ProvideHttpObjectAggregatorFactory.java | 31 ++++ ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ++++ ...oisModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ++++++ ...isModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ++++++ ...WhoisModule_ProvideSslProviderFactory.java | 30 ++++ ...viderHttpWhoisHandlerProvidersFactory.java | 58 +++++++ ...iderHttpsWhoisHandlerProvidersFactory.java | 75 +++++++++ .../blackbox/WebWhoisToken_Factory.java | 25 +++ .../handlers/ActionHandler_Factory.java | 25 +++ .../handlers/RedirectHandler_Factory.java | 25 +++ .../SslClientInitializer_Factory.java | 35 ++++ .../handlers/WebWhoIsHandler_Factory.java | 25 +++ .../WebWhoisActionHandler_Factory.java | 25 +++ .../DaggerProberModule_ProberComponent.java | 155 ++++++++++++++++++ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...odule_ProvidePortToProtocolMapFactory.java | 43 +++++ .../TokenModule_DomainNameFactory.java | 27 +++ .../TokenModule_ProvideTokenFactory.java | 35 ++++ ...sModule_ProvideHttpClientCodecFactory.java | 31 ++++ ...le_ProvideHttpObjectAggregatorFactory.java | 31 ++++ ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 54 ++++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 54 ++++++ ...WhoisModule_ProvideSslProviderFactory.java | 30 ++++ ...viderHttpWhoisHandlerProvidersFactory.java | 58 +++++++ ...iderHttpsWhoisHandlerProvidersFactory.java | 75 +++++++++ .../DaggerProberModule_ProberComponent.java | 154 +++++++++++++++++ .../DaggerTestModule_TestComponent.java | 46 ++++++ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ++++ ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ++++ ...odule_ProvidePortToProtocolMapFactory.java | 42 +++++ .../blackbox/TestHandler_Factory.java | 25 +++ .../TestModule_ProvideHandlersFactory.java | 38 +++++ .../TestProtocol_MembersInjector.java | 36 ++++ .../TokenModule_DomainNameFactory.java | 27 +++ .../TokenModule_ProvideTokenFactory.java | 35 ++++ ...sModule_ProvideHttpClientCodecFactory.java | 31 ++++ ...le_ProvideHttpObjectAggregatorFactory.java | 31 ++++ ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ++++ ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ++++++ ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ++++++ ...WhoisModule_ProvideSslProviderFactory.java | 30 ++++ ...viderHttpWhoisHandlerProvidersFactory.java | 58 +++++++ ...iderHttpsWhoisHandlerProvidersFactory.java | 75 +++++++++ 72 files changed, 3018 insertions(+) create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java create mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java new file mode 100644 index 00000000000..8a727c63bbb --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ActionHandler_Factory implements Factory { + private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); + + @Override + public ActionHandler get() { + return new ActionHandler(); + } + + public static ActionHandler_Factory create() { + return INSTANCE; + } + + public static ActionHandler newActionHandler() { + return new ActionHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java new file mode 100644 index 00000000000..39af08b1e60 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java @@ -0,0 +1,154 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { + private final ProberModule proberModule; + + private Provider provideHttpWhoisPortProvider; + + private Provider provideHttpWhoisHostProvider; + + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider provideHttpsWhoisPortProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerProberModule_ProberComponent( + ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { + this.proberModule = proberModuleParam; + initialize(proberModuleParam, webWhoisModuleParam); + } + + public static Builder builder() { + return new Builder(); + } + + public static ProberModule.ProberComponent create() { + return new Builder().build(); + } + + private Set getSetOfProtocol() { + return ImmutableSet.of( + provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); + } + + private WebWhoisToken getWebWhoisToken() { + return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); + } + + @SuppressWarnings("unchecked") + private void initialize( + final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { + this.provideHttpWhoisPortProvider = + ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); + this.provideHttpWhoisHostProvider = + WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + provideHttpWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpWhoisHandlerProvidersProvider)); + this.provideHttpsWhoisPortProvider = + ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + provideHttpsWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public ImmutableMap providePortToProtocolMap() { + return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( + proberModule, getSetOfProtocol()); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); + } + + public static final class Builder { + private ProberModule proberModule; + + private WebWhoisModule webWhoisModule; + + private Builder() {} + + public Builder proberModule(ProberModule proberModule) { + this.proberModule = Preconditions.checkNotNull(proberModule); + return this; + } + + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public ProberModule.ProberComponent build() { + if (proberModule == null) { + this.proberModule = new ProberModule(); + } + if (webWhoisModule == null) { + this.webWhoisModule = new WebWhoisModule(); + } + return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); + } + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java new file mode 100644 index 00000000000..ba272c4730a --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java @@ -0,0 +1,119 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerWebWhoisModule_WebWhoisComponent + implements WebWhoisModule.WebWhoisComponent { + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerWebWhoisModule_WebWhoisComponent() { + + initialize(); + } + + public static Builder builder() { + return new Builder(); + } + + public static WebWhoisModule.WebWhoisComponent create() { + return new Builder().build(); + } + + @SuppressWarnings("unchecked") + private void initialize() { + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + WebWhoisModule_HttpWhoisPortFactory.create(), + WebWhoisModule_HttpWhoisHostFactory.create(), + providerHttpWhoisHandlerProvidersProvider)); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + WebWhoisModule_HttpsWhoisPortFactory.create(), + WebWhoisModule_HttpsWhoisHostFactory.create(), + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public Protocol provideHttpWhoisProtocol() { + return provideHttpWhoisProtocolProvider.get(); + } + + @Override + public Protocol provideHttpsWhoisProtocol() { + return provideHttpsWhoisProtocolProvider.get(); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(); + } + + public static final class Builder { + private Builder() {} + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public WebWhoisModule.WebWhoisComponent build() { + return new DaggerWebWhoisModule_WebWhoisComponent(); + } + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java new file mode 100644 index 00000000000..659d36c8249 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoIsPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoIsPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoIsPort(module); + } + + public static ProberModule_ProvideHttpWhoIsPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoIsPortFactory(module); + } + + public static int proxyProvideHttpWhoIsPort(ProberModule instance) { + return instance.provideHttpWhoIsPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..93f9e4f9f48 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(ProberModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..4d560ae3c94 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisProtocolFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisProtocol(module); + } + + public static ProberModule_ProvideHttpWhoisProtocolFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisProtocolFactory(module); + } + + public static int proxyProvideHttpWhoisProtocol(ProberModule instance) { + return instance.provideHttpWhoisProtocol(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java new file mode 100644 index 00000000000..a49efddd550 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoIsPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoIsPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoIsPort(module); + } + + public static ProberModule_ProvideHttpsWhoIsPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoIsPortFactory(module); + } + + public static int proxyProvideHttpsWhoIsPort(ProberModule instance) { + return instance.provideHttpsWhoIsPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..0aee5faf959 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(ProberModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..faaae10cb72 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisProtocolFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisProtocol(module); + } + + public static ProberModule_ProvideHttpsWhoisProtocolFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisProtocolFactory(module); + } + + public static int proxyProvideHttpsWhoisProtocol(ProberModule instance) { + return instance.provideHttpsWhoisProtocol(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java new file mode 100644 index 00000000000..7ab2e4e9dd9 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java @@ -0,0 +1,42 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableMap; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvidePortToProtocolMapFactory + implements Factory> { + private final ProberModule module; + + private final Provider> protocolSetProvider; + + public ProberModule_ProvidePortToProtocolMapFactory( + ProberModule module, Provider> protocolSetProvider) { + this.module = module; + this.protocolSetProvider = protocolSetProvider; + } + + @Override + public ImmutableMap get() { + return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); + } + + public static ProberModule_ProvidePortToProtocolMapFactory create( + ProberModule module, Provider> protocolSetProvider) { + return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); + } + + public static ImmutableMap proxyProvidePortToProtocolMap( + ProberModule instance, Set protocolSet) { + return Preconditions.checkNotNull( + instance.providePortToProtocolMap(protocolSet), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java new file mode 100644 index 00000000000..a8d428b93c2 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProbingStepWeb_Factory implements Factory { + private final Provider protocolProvider; + + public ProbingStepWeb_Factory(Provider protocolProvider) { + this.protocolProvider = protocolProvider; + } + + @Override + public ProbingStepWeb get() { + return new ProbingStepWeb(protocolProvider.get()); + } + + public static ProbingStepWeb_Factory create(Provider protocolProvider) { + return new ProbingStepWeb_Factory(protocolProvider); + } + + public static ProbingStepWeb newProbingStepWeb(Protocol protocol) { + return new ProbingStepWeb(protocol); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java new file mode 100644 index 00000000000..1e8ba7f6af6 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProbingStep_Factory implements Factory> { + @SuppressWarnings("rawtypes") + private static final ProbingStep_Factory INSTANCE = new ProbingStep_Factory(); + + @Override + public ProbingStep get() { + return new ProbingStep(); + } + + @SuppressWarnings("unchecked") + public static ProbingStep_Factory create() { + return INSTANCE; + } + + public static ProbingStep newProbingStep() { + return new ProbingStep(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java new file mode 100644 index 00000000000..fd4bf43308d --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java @@ -0,0 +1,45 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestToken_Factory implements Factory { + private final Provider actionHandlerProvider; + + private final Provider domainNameProvider; + + private final Provider protocolProvider; + + public TestToken_Factory( + Provider actionHandlerProvider, + Provider domainNameProvider, + Provider protocolProvider) { + this.actionHandlerProvider = actionHandlerProvider; + this.domainNameProvider = domainNameProvider; + this.protocolProvider = protocolProvider; + } + + @Override + public TestToken get() { + TestToken instance = new TestToken(actionHandlerProvider.get(), domainNameProvider.get()); + TestToken_MembersInjector.injectProtocol(instance, protocolProvider.get()); + return instance; + } + + public static TestToken_Factory create( + Provider actionHandlerProvider, + Provider domainNameProvider, + Provider protocolProvider) { + return new TestToken_Factory(actionHandlerProvider, domainNameProvider, protocolProvider); + } + + public static TestToken newTestToken(ActionHandler actionHandler, String domainName) { + return new TestToken(actionHandler, domainName); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java new file mode 100644 index 00000000000..db846ba4a36 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.MembersInjector; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestToken_MembersInjector implements MembersInjector { + private final Provider protocolProvider; + + public TestToken_MembersInjector(Provider protocolProvider) { + this.protocolProvider = protocolProvider; + } + + public static MembersInjector create(Provider protocolProvider) { + return new TestToken_MembersInjector(protocolProvider); + } + + @Override + public void injectMembers(TestToken instance) { + injectProtocol(instance, protocolProvider.get()); + } + + public static void injectProtocol(TestToken instance, Protocol protocol) { + instance.protocol = protocol; + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java new file mode 100644 index 00000000000..1dc41bf0e16 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_DomainNameFactory implements Factory { + private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); + + @Override + public String get() { + return proxyDomainName(); + } + + public static TokenModule_DomainNameFactory create() { + return INSTANCE; + } + + public static String proxyDomainName() { + return Preconditions.checkNotNull( + TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java new file mode 100644 index 00000000000..afc66775c9d --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_ProvideTokenFactory implements Factory { + private final Provider tokenProvider; + + public TokenModule_ProvideTokenFactory(Provider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public Token get() { + return proxyProvideToken(tokenProvider.get()); + } + + public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { + return new TokenModule_ProvideTokenFactory(tokenProvider); + } + + public static Token proxyProvideToken(WebWhoisToken token) { + return Preconditions.checkNotNull( + TokenModule.provideToken(token), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java new file mode 100644 index 00000000000..feab7f7d227 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.MembersInjector; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class Token_MembersInjector implements MembersInjector { + private final Provider actionHandlerProvider; + + public Token_MembersInjector(Provider actionHandlerProvider) { + this.actionHandlerProvider = actionHandlerProvider; + } + + public static MembersInjector create(Provider actionHandlerProvider) { + return new Token_MembersInjector(actionHandlerProvider); + } + + @Override + public void injectMembers(Token instance) { + injectActionHandler(instance, actionHandlerProvider.get()); + } + + public static void injectActionHandler(Object instance, ActionHandler actionHandler) { + ((Token) instance).actionHandler = actionHandler; + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java new file mode 100644 index 00000000000..3d153c08fdb --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.Tokens; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisToken_Factory implements Factory { + private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); + + @Override + public WebWhoisToken get() { + return new WebWhoisToken(); + } + + public static WebWhoisToken_Factory create() { + return INSTANCE; + } + + public static WebWhoisToken newWebWhoisToken() { + return new WebWhoisToken(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java new file mode 100644 index 00000000000..f2f34a674d3 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java @@ -0,0 +1,28 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpWhoisHostFactory implements Factory { + private static final WebWhoisModule_HttpWhoisHostFactory INSTANCE = + new WebWhoisModule_HttpWhoisHostFactory(); + + @Override + public String get() { + return proxyHttpWhoisHost(); + } + + public static WebWhoisModule_HttpWhoisHostFactory create() { + return INSTANCE; + } + + public static String proxyHttpWhoisHost() { + return Preconditions.checkNotNull( + WebWhoisModule.httpWhoisHost(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java new file mode 100644 index 00000000000..67ab24c06fd --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java @@ -0,0 +1,28 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpWhoisPathFactory implements Factory { + private static final WebWhoisModule_HttpWhoisPathFactory INSTANCE = + new WebWhoisModule_HttpWhoisPathFactory(); + + @Override + public String get() { + return proxyHttpWhoisPath(); + } + + public static WebWhoisModule_HttpWhoisPathFactory create() { + return INSTANCE; + } + + public static String proxyHttpWhoisPath() { + return Preconditions.checkNotNull( + WebWhoisModule.httpWhoisPath(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java new file mode 100644 index 00000000000..4a29a990b67 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java @@ -0,0 +1,26 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpWhoisPortFactory implements Factory { + private static final WebWhoisModule_HttpWhoisPortFactory INSTANCE = + new WebWhoisModule_HttpWhoisPortFactory(); + + @Override + public Integer get() { + return proxyHttpWhoisPort(); + } + + public static WebWhoisModule_HttpWhoisPortFactory create() { + return INSTANCE; + } + + public static int proxyHttpWhoisPort() { + return WebWhoisModule.httpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java new file mode 100644 index 00000000000..f8a7fae07a8 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpsWhoisHostFactory implements Factory { + private static final WebWhoisModule_HttpsWhoisHostFactory INSTANCE = + new WebWhoisModule_HttpsWhoisHostFactory(); + + @Override + public String get() { + return proxyHttpsWhoisHost(); + } + + public static WebWhoisModule_HttpsWhoisHostFactory create() { + return INSTANCE; + } + + public static String proxyHttpsWhoisHost() { + return Preconditions.checkNotNull( + WebWhoisModule.httpsWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java new file mode 100644 index 00000000000..4cabb7b5384 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpsWhoisPathFactory implements Factory { + private static final WebWhoisModule_HttpsWhoisPathFactory INSTANCE = + new WebWhoisModule_HttpsWhoisPathFactory(); + + @Override + public String get() { + return proxyHttpsWhoisPath(); + } + + public static WebWhoisModule_HttpsWhoisPathFactory create() { + return INSTANCE; + } + + public static String proxyHttpsWhoisPath() { + return Preconditions.checkNotNull( + WebWhoisModule.httpsWhoisPath(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java new file mode 100644 index 00000000000..30f4564213a --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java @@ -0,0 +1,26 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_HttpsWhoisPortFactory implements Factory { + private static final WebWhoisModule_HttpsWhoisPortFactory INSTANCE = + new WebWhoisModule_HttpsWhoisPortFactory(); + + @Override + public Integer get() { + return proxyHttpsWhoisPort(); + } + + public static WebWhoisModule_HttpsWhoisPortFactory create() { + return INSTANCE; + } + + public static int proxyHttpsWhoisPort() { + return WebWhoisModule.httpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java new file mode 100644 index 00000000000..7c756174314 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpClientCodec; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpClientCodecFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = + new WebWhoisModule_ProvideHttpClientCodecFactory(); + + @Override + public HttpClientCodec get() { + return proxyProvideHttpClientCodec(); + } + + public static WebWhoisModule_ProvideHttpClientCodecFactory create() { + return INSTANCE; + } + + public static HttpClientCodec proxyProvideHttpClientCodec() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpClientCodec(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java new file mode 100644 index 00000000000..20785cde372 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = + new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); + + @Override + public HttpObjectAggregator get() { + return proxyProvideHttpObjectAggregator(); + } + + public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { + return INSTANCE; + } + + public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpObjectAggregator(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java new file mode 100644 index 00000000000..7087ab940bc --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java @@ -0,0 +1,32 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public String get() { + return proxyProvideHttpWhoisHost(module); + } + + public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); + } + + public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { + return Preconditions.checkNotNull( + instance.provideHttpWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..a4aaf24978e --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisPortFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisPortFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static WebWhoisModule_ProvideHttpWhoisPortFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(WebWhoisModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..ed7e62f3a5f --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final Provider httpWhoisPortProvider; + + private final Provider httpWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpWhoisProtocolFactory( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpWhoisPortProvider = httpWhoisPortProvider; + this.httpWhoisHostProvider = httpWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpWhoisProtocol( + httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( + httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpWhoisProtocol( + int httpWhoisPort, + String httpWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..c3d7c6546e5 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisPortFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpsWhoisPortFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static WebWhoisModule_ProvideHttpsWhoisPortFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(WebWhoisModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..4ab50681eea --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final Provider httpsWhoisPortProvider; + + private final Provider httpsWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpsWhoisPortProvider = httpsWhoisPortProvider; + this.httpsWhoisHostProvider = httpsWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpsWhoisProtocol( + httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpsWhoisProtocol( + int httpsWhoisPort, + String httpsWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java new file mode 100644 index 00000000000..7579cc752cf --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { + private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = + new WebWhoisModule_ProvideSslProviderFactory(); + + @Override + public SslProvider get() { + return proxyProvideSslProvider(); + } + + public static WebWhoisModule_ProvideSslProviderFactory create() { + return INSTANCE; + } + + public static SslProvider proxyProvideSslProvider() { + return Preconditions.checkNotNull( + WebWhoisModule.provideSslProvider(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..37431babcb9 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java @@ -0,0 +1,58 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpWhoisHandlerProviders( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..adf393894e8 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java @@ -0,0 +1,75 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider> sslClientInitializerProvider; + + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.sslClientInitializerProvider = sslClientInitializerProvider; + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpsWhoisHandlerProviders( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java new file mode 100644 index 00000000000..6c840214a11 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisToken_Factory implements Factory { + private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); + + @Override + public WebWhoisToken get() { + return new WebWhoisToken(); + } + + public static WebWhoisToken_Factory create() { + return INSTANCE; + } + + public static WebWhoisToken newWebWhoisToken() { + return new WebWhoisToken(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java new file mode 100644 index 00000000000..d94df8b392f --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ActionHandler_Factory implements Factory { + private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); + + @Override + public ActionHandler get() { + return new ActionHandler(); + } + + public static ActionHandler_Factory create() { + return INSTANCE; + } + + public static ActionHandler newActionHandler() { + return new ActionHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java new file mode 100644 index 00000000000..ddf10cf830b --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class RedirectHandler_Factory implements Factory { + private static final RedirectHandler_Factory INSTANCE = new RedirectHandler_Factory(); + + @Override + public RedirectHandler get() { + return new RedirectHandler(); + } + + public static RedirectHandler_Factory create() { + return INSTANCE; + } + + public static RedirectHandler newRedirectHandler() { + return new RedirectHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java new file mode 100644 index 00000000000..7fa480f418e --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import io.netty.channel.Channel; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class SslClientInitializer_Factory + implements Factory> { + private final Provider sslProvider; + + public SslClientInitializer_Factory(Provider sslProvider) { + this.sslProvider = sslProvider; + } + + @Override + public SslClientInitializer get() { + return new SslClientInitializer(sslProvider.get()); + } + + public static SslClientInitializer_Factory create( + Provider sslProvider) { + return new SslClientInitializer_Factory(sslProvider); + } + + public static SslClientInitializer newSslClientInitializer( + SslProvider sslProvider) { + return new SslClientInitializer(sslProvider); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java new file mode 100644 index 00000000000..26b68fdc09c --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoIsHandler_Factory implements Factory { + private static final WebWhoIsHandler_Factory INSTANCE = new WebWhoIsHandler_Factory(); + + @Override + public WebWhoIsHandler get() { + return new WebWhoIsHandler(); + } + + public static WebWhoIsHandler_Factory create() { + return INSTANCE; + } + + public static WebWhoIsHandler newWebWhoIsHandler() { + return new WebWhoIsHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java new file mode 100644 index 00000000000..dc008e1a724 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox.handlers; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisActionHandler_Factory implements Factory { + private static final WebWhoisActionHandler_Factory INSTANCE = new WebWhoisActionHandler_Factory(); + + @Override + public WebWhoisActionHandler get() { + return new WebWhoisActionHandler(); + } + + public static WebWhoisActionHandler_Factory create() { + return INSTANCE; + } + + public static WebWhoisActionHandler newWebWhoisActionHandler() { + return new WebWhoisActionHandler(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java new file mode 100644 index 00000000000..b7971395941 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java @@ -0,0 +1,155 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { + private final ProberModule proberModule; + + private Provider provideHttpWhoisPortProvider; + + private Provider provideHttpWhoisHostProvider; + + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider provideHttpsWhoisPortProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerProberModule_ProberComponent( + ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { + this.proberModule = proberModuleParam; + initialize(proberModuleParam, webWhoisModuleParam); + } + + public static Builder builder() { + return new Builder(); + } + + public static ProberModule.ProberComponent create() { + return new Builder().build(); + } + + private Set getSetOfProtocol() { + return ImmutableSet.of( + provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); + } + + private WebWhoisToken getWebWhoisToken() { + return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); + } + + @SuppressWarnings("unchecked") + private void initialize( + final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { + this.provideHttpWhoisPortProvider = + ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); + this.provideHttpWhoisHostProvider = + WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + provideHttpWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpWhoisHandlerProvidersProvider)); + this.provideHttpsWhoisPortProvider = + ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + provideHttpsWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public ImmutableMap providePortToProtocolMap() { + return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( + proberModule, getSetOfProtocol()); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); + } + + public static final class Builder { + private ProberModule proberModule; + + private WebWhoisModule webWhoisModule; + + private Builder() {} + + public Builder proberModule(ProberModule proberModule) { + this.proberModule = Preconditions.checkNotNull(proberModule); + return this; + } + + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public ProberModule.ProberComponent build() { + if (proberModule == null) { + this.proberModule = new ProberModule(); + } + if (webWhoisModule == null) { + this.webWhoisModule = new WebWhoisModule(); + } + return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); + } + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..955698498db --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(ProberModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..0b97c8dbb72 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(ProberModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java new file mode 100644 index 00000000000..e0597aa25f5 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java @@ -0,0 +1,43 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableMap; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvidePortToProtocolMapFactory + implements Factory> { + private final ProberModule module; + + private final Provider> protocolSetProvider; + + public ProberModule_ProvidePortToProtocolMapFactory( + ProberModule module, Provider> protocolSetProvider) { + this.module = module; + this.protocolSetProvider = protocolSetProvider; + } + + @Override + public ImmutableMap get() { + return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); + } + + public static ProberModule_ProvidePortToProtocolMapFactory create( + ProberModule module, Provider> protocolSetProvider) { + return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); + } + + public static ImmutableMap proxyProvidePortToProtocolMap( + ProberModule instance, Set protocolSet) { + return Preconditions.checkNotNull( + instance.providePortToProtocolMap(protocolSet), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java new file mode 100644 index 00000000000..20e2ca11502 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_DomainNameFactory implements Factory { + private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); + + @Override + public String get() { + return proxyDomainName(); + } + + public static TokenModule_DomainNameFactory create() { + return INSTANCE; + } + + public static String proxyDomainName() { + return Preconditions.checkNotNull( + TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java new file mode 100644 index 00000000000..e6628332802 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_ProvideTokenFactory implements Factory { + private final Provider tokenProvider; + + public TokenModule_ProvideTokenFactory(Provider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public Token get() { + return proxyProvideToken(tokenProvider.get()); + } + + public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { + return new TokenModule_ProvideTokenFactory(tokenProvider); + } + + public static Token proxyProvideToken(WebWhoisToken token) { + return Preconditions.checkNotNull( + TokenModule.provideToken(token), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java new file mode 100644 index 00000000000..31710bed6eb --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpClientCodec; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpClientCodecFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = + new WebWhoisModule_ProvideHttpClientCodecFactory(); + + @Override + public HttpClientCodec get() { + return proxyProvideHttpClientCodec(); + } + + public static WebWhoisModule_ProvideHttpClientCodecFactory create() { + return INSTANCE; + } + + public static HttpClientCodec proxyProvideHttpClientCodec() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpClientCodec(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java new file mode 100644 index 00000000000..b69df1a2f7d --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = + new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); + + @Override + public HttpObjectAggregator get() { + return proxyProvideHttpObjectAggregator(); + } + + public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { + return INSTANCE; + } + + public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpObjectAggregator(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java new file mode 100644 index 00000000000..bacebd82f49 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java @@ -0,0 +1,32 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public String get() { + return proxyProvideHttpWhoisHost(module); + } + + public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); + } + + public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { + return Preconditions.checkNotNull( + instance.provideHttpWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..0d098288569 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,54 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final Provider httpWhoisPortProvider; + + private final Provider httpWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpWhoisProtocolFactory( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpWhoisPortProvider = httpWhoisPortProvider; + this.httpWhoisHostProvider = httpWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpWhoisProtocol( + httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( + httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpWhoisProtocol( + int httpWhoisPort, + String httpWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..c40cde16709 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,54 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final Provider httpsWhoisPortProvider; + + private final Provider httpsWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpsWhoisPortProvider = httpsWhoisPortProvider; + this.httpsWhoisHostProvider = httpsWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpsWhoisProtocol( + httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpsWhoisProtocol( + int httpsWhoisPort, + String httpsWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java new file mode 100644 index 00000000000..208d9c7212e --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox.modules; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { + private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = + new WebWhoisModule_ProvideSslProviderFactory(); + + @Override + public SslProvider get() { + return proxyProvideSslProvider(); + } + + public static WebWhoisModule_ProvideSslProviderFactory create() { + return INSTANCE; + } + + public static SslProvider proxyProvideSslProvider() { + return Preconditions.checkNotNull( + WebWhoisModule.provideSslProvider(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..81eb6efc487 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java @@ -0,0 +1,58 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpWhoisHandlerProviders( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..e18a43dd7a8 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java @@ -0,0 +1,75 @@ +package google.registry.monitoring.blackbox.modules; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider> sslClientInitializerProvider; + + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.sslClientInitializerProvider = sslClientInitializerProvider; + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpsWhoisHandlerProviders( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java new file mode 100644 index 00000000000..39af08b1e60 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java @@ -0,0 +1,154 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import dagger.internal.DoubleCheck; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { + private final ProberModule proberModule; + + private Provider provideHttpWhoisPortProvider; + + private Provider provideHttpWhoisHostProvider; + + private Provider>> + providerHttpWhoisHandlerProvidersProvider; + + private Provider provideHttpWhoisProtocolProvider; + + private Provider provideHttpsWhoisPortProvider; + + private Provider> sslClientInitializerProvider; + + private Provider>> + providerHttpsWhoisHandlerProvidersProvider; + + private Provider provideHttpsWhoisProtocolProvider; + + private DaggerProberModule_ProberComponent( + ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { + this.proberModule = proberModuleParam; + initialize(proberModuleParam, webWhoisModuleParam); + } + + public static Builder builder() { + return new Builder(); + } + + public static ProberModule.ProberComponent create() { + return new Builder().build(); + } + + private Set getSetOfProtocol() { + return ImmutableSet.of( + provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); + } + + private WebWhoisToken getWebWhoisToken() { + return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); + } + + @SuppressWarnings("unchecked") + private void initialize( + final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { + this.provideHttpWhoisPortProvider = + ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); + this.provideHttpWhoisHostProvider = + WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); + this.providerHttpWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( + provideHttpWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpWhoisHandlerProvidersProvider)); + this.provideHttpsWhoisPortProvider = + ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); + this.sslClientInitializerProvider = + DoubleCheck.provider( + (Provider) + SslClientInitializer_Factory.create( + WebWhoisModule_ProvideSslProviderFactory.create())); + this.providerHttpsWhoisHandlerProvidersProvider = + WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( + sslClientInitializerProvider, + WebWhoisModule_ProvideHttpClientCodecFactory.create(), + WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), + WebWhoisActionHandler_Factory.create()); + this.provideHttpsWhoisProtocolProvider = + DoubleCheck.provider( + WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( + provideHttpsWhoisPortProvider, + provideHttpWhoisHostProvider, + providerHttpsWhoisHandlerProvidersProvider)); + } + + @Override + public ImmutableMap providePortToProtocolMap() { + return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( + proberModule, getSetOfProtocol()); + } + + @Override + public Token provideToken() { + return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); + } + + public static final class Builder { + private ProberModule proberModule; + + private WebWhoisModule webWhoisModule; + + private Builder() {} + + public Builder proberModule(ProberModule proberModule) { + this.proberModule = Preconditions.checkNotNull(proberModule); + return this; + } + + public Builder webWhoisModule(WebWhoisModule webWhoisModule) { + this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); + return this; + } + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder tokenModule(TokenModule tokenModule) { + Preconditions.checkNotNull(tokenModule); + return this; + } + + public ProberModule.ProberComponent build() { + if (proberModule == null) { + this.proberModule = new ProberModule(); + } + if (webWhoisModule == null) { + this.webWhoisModule = new WebWhoisModule(); + } + return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); + } + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java new file mode 100644 index 00000000000..45032a9c7ba --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java @@ -0,0 +1,46 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class DaggerTestModule_TestComponent implements TestModule.TestComponent { + private DaggerTestModule_TestComponent() {} + + public static Builder builder() { + return new Builder(); + } + + public static TestModule.TestComponent create() { + return new Builder().build(); + } + + @Override + public ImmutableList> provideHandlers() { + return TestModule_ProvideHandlersFactory.proxyProvideHandlers(TestHandler_Factory.create()); + } + + public static final class Builder { + private Builder() {} + + /** + * @deprecated This module is declared, but an instance is not used in the component. This + * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. + */ + @Deprecated + public Builder testModule(TestModule testModule) { + Preconditions.checkNotNull(testModule); + return this; + } + + public TestModule.TestComponent build() { + return new DaggerTestModule_TestComponent(); + } + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java new file mode 100644 index 00000000000..93f9e4f9f48 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpWhoisPort(module); + } + + public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpWhoisPortFactory(module); + } + + public static int proxyProvideHttpWhoisPort(ProberModule instance) { + return instance.provideHttpWhoisPort(); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java new file mode 100644 index 00000000000..0aee5faf959 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java @@ -0,0 +1,29 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { + private final ProberModule module; + + public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { + this.module = module; + } + + @Override + public Integer get() { + return proxyProvideHttpsWhoisPort(module); + } + + public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { + return new ProberModule_ProvideHttpsWhoisPortFactory(module); + } + + public static int proxyProvideHttpsWhoisPort(ProberModule instance) { + return instance.provideHttpsWhoisPort(); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java new file mode 100644 index 00000000000..7ab2e4e9dd9 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java @@ -0,0 +1,42 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableMap; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import java.util.Set; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class ProberModule_ProvidePortToProtocolMapFactory + implements Factory> { + private final ProberModule module; + + private final Provider> protocolSetProvider; + + public ProberModule_ProvidePortToProtocolMapFactory( + ProberModule module, Provider> protocolSetProvider) { + this.module = module; + this.protocolSetProvider = protocolSetProvider; + } + + @Override + public ImmutableMap get() { + return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); + } + + public static ProberModule_ProvidePortToProtocolMapFactory create( + ProberModule module, Provider> protocolSetProvider) { + return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); + } + + public static ImmutableMap proxyProvidePortToProtocolMap( + ProberModule instance, Set protocolSet) { + return Preconditions.checkNotNull( + instance.providePortToProtocolMap(protocolSet), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java new file mode 100644 index 00000000000..50616d20699 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java @@ -0,0 +1,25 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestHandler_Factory implements Factory { + private static final TestHandler_Factory INSTANCE = new TestHandler_Factory(); + + @Override + public TestHandler get() { + return new TestHandler(); + } + + public static TestHandler_Factory create() { + return INSTANCE; + } + + public static TestHandler newTestHandler() { + return new TestHandler(); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java new file mode 100644 index 00000000000..79e40ee2d4a --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java @@ -0,0 +1,38 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestModule_ProvideHandlersFactory + implements Factory>> { + private final Provider testHandlerProvider; + + public TestModule_ProvideHandlersFactory(Provider testHandlerProvider) { + this.testHandlerProvider = testHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProvideHandlers(testHandlerProvider); + } + + public static TestModule_ProvideHandlersFactory create( + Provider testHandlerProvider) { + return new TestModule_ProvideHandlersFactory(testHandlerProvider); + } + + public static ImmutableList> proxyProvideHandlers( + Provider testHandlerProvider) { + return Preconditions.checkNotNull( + TestModule.provideHandlers(testHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java new file mode 100644 index 00000000000..75b788ec968 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java @@ -0,0 +1,36 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.MembersInjector; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TestProtocol_MembersInjector implements MembersInjector { + private final Provider>> + handlerProvidersProvider; + + public TestProtocol_MembersInjector( + Provider>> handlerProvidersProvider) { + this.handlerProvidersProvider = handlerProvidersProvider; + } + + public static MembersInjector create( + Provider>> handlerProvidersProvider) { + return new TestProtocol_MembersInjector(handlerProvidersProvider); + } + + @Override + public void injectMembers(TestProtocol instance) { + injectTestProtocolHandlers(instance, handlerProvidersProvider.get()); + } + + public static void injectTestProtocolHandlers( + TestProtocol instance, ImmutableList> handlerProviders) { + instance.TestProtocolHandlers(handlerProviders); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java new file mode 100644 index 00000000000..1dc41bf0e16 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java @@ -0,0 +1,27 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_DomainNameFactory implements Factory { + private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); + + @Override + public String get() { + return proxyDomainName(); + } + + public static TokenModule_DomainNameFactory create() { + return INSTANCE; + } + + public static String proxyDomainName() { + return Preconditions.checkNotNull( + TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java new file mode 100644 index 00000000000..afc66775c9d --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java @@ -0,0 +1,35 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class TokenModule_ProvideTokenFactory implements Factory { + private final Provider tokenProvider; + + public TokenModule_ProvideTokenFactory(Provider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public Token get() { + return proxyProvideToken(tokenProvider.get()); + } + + public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { + return new TokenModule_ProvideTokenFactory(tokenProvider); + } + + public static Token proxyProvideToken(WebWhoisToken token) { + return Preconditions.checkNotNull( + TokenModule.provideToken(token), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java new file mode 100644 index 00000000000..7c756174314 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpClientCodec; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpClientCodecFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = + new WebWhoisModule_ProvideHttpClientCodecFactory(); + + @Override + public HttpClientCodec get() { + return proxyProvideHttpClientCodec(); + } + + public static WebWhoisModule_ProvideHttpClientCodecFactory create() { + return INSTANCE; + } + + public static HttpClientCodec proxyProvideHttpClientCodec() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpClientCodec(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java new file mode 100644 index 00000000000..20785cde372 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java @@ -0,0 +1,31 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory + implements Factory { + private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = + new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); + + @Override + public HttpObjectAggregator get() { + return proxyProvideHttpObjectAggregator(); + } + + public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { + return INSTANCE; + } + + public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpObjectAggregator(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java new file mode 100644 index 00000000000..7087ab940bc --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java @@ -0,0 +1,32 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { + private final WebWhoisModule module; + + public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { + this.module = module; + } + + @Override + public String get() { + return proxyProvideHttpWhoisHost(module); + } + + public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { + return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); + } + + public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { + return Preconditions.checkNotNull( + instance.provideHttpWhoisHost(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java new file mode 100644 index 00000000000..ed7e62f3a5f --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { + private final Provider httpWhoisPortProvider; + + private final Provider httpWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpWhoisProtocolFactory( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpWhoisPortProvider = httpWhoisPortProvider; + this.httpWhoisHostProvider = httpWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpWhoisProtocol( + httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( + Provider httpWhoisPortProvider, + Provider httpWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( + httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpWhoisProtocol( + int httpWhoisPort, + String httpWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java new file mode 100644 index 00000000000..4ab50681eea --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java @@ -0,0 +1,53 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { + private final Provider httpsWhoisPortProvider; + + private final Provider httpsWhoisHostProvider; + + private final Provider>> + handlerProvidersProvider; + + public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + this.httpsWhoisPortProvider = httpsWhoisPortProvider; + this.httpsWhoisHostProvider = httpsWhoisHostProvider; + this.handlerProvidersProvider = handlerProvidersProvider; + } + + @Override + public Protocol get() { + return proxyProvideHttpsWhoisProtocol( + httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); + } + + public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( + Provider httpsWhoisPortProvider, + Provider httpsWhoisHostProvider, + Provider>> handlerProvidersProvider) { + return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( + httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); + } + + public static Protocol proxyProvideHttpsWhoisProtocol( + int httpsWhoisPort, + String httpsWhoisHost, + ImmutableList> handlerProviders) { + return Preconditions.checkNotNull( + WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java new file mode 100644 index 00000000000..7579cc752cf --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java @@ -0,0 +1,30 @@ +package google.registry.monitoring.blackbox; + +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import io.netty.handler.ssl.SslProvider; +import javax.annotation.Generated; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { + private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = + new WebWhoisModule_ProvideSslProviderFactory(); + + @Override + public SslProvider get() { + return proxyProvideSslProvider(); + } + + public static WebWhoisModule_ProvideSslProviderFactory create() { + return INSTANCE; + } + + public static SslProvider proxyProvideSslProvider() { + return Preconditions.checkNotNull( + WebWhoisModule.provideSslProvider(), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..37431babcb9 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java @@ -0,0 +1,58 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpWhoisHandlerProviders( + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpWhoisHandlerProviders( + httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java new file mode 100644 index 00000000000..adf393894e8 --- /dev/null +++ b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java @@ -0,0 +1,75 @@ +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import dagger.internal.Factory; +import dagger.internal.Preconditions; +import google.registry.monitoring.blackbox.handlers.SslClientInitializer; +import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated( + value = "dagger.internal.codegen.ComponentProcessor", + comments = "https://google.github.io/dagger" +) +public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory + implements Factory>> { + private final Provider> sslClientInitializerProvider; + + private final Provider httpClientCodecProvider; + + private final Provider httpObjectAggregatorProvider; + + private final Provider webWhoisActionHandlerProvider; + + public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + this.sslClientInitializerProvider = sslClientInitializerProvider; + this.httpClientCodecProvider = httpClientCodecProvider; + this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; + this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; + } + + @Override + public ImmutableList> get() { + return proxyProviderHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider); + } + + public static ImmutableList> + proxyProviderHttpsWhoisHandlerProviders( + Provider> sslClientInitializerProvider, + Provider httpClientCodecProvider, + Provider httpObjectAggregatorProvider, + Provider webWhoisActionHandlerProvider) { + return Preconditions.checkNotNull( + WebWhoisModule.providerHttpsWhoisHandlerProviders( + sslClientInitializerProvider, + httpClientCodecProvider, + httpObjectAggregatorProvider, + webWhoisActionHandlerProvider), + "Cannot return null from a non-@Nullable @Provides method"); + } +} From c9287789b4c27d42aeb33d01225165c416b31b72 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:29:25 -0400 Subject: [PATCH 150/337] Removed all generated java --- .../blackbox/ActionHandler_Factory.java | 25 --- .../DaggerProberModule_ProberComponent.java | 154 ----------------- ...aggerWebWhoisModule_WebWhoisComponent.java | 119 -------------- ...berModule_ProvideHttpWhoIsPortFactory.java | 29 ---- ...berModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 29 ---- ...erModule_ProvideHttpsWhoIsPortFactory.java | 29 ---- ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...dule_ProvideHttpsWhoisProtocolFactory.java | 29 ---- ...odule_ProvidePortToProtocolMapFactory.java | 42 ----- .../blackbox/ProbingStepWeb_Factory.java | 30 ---- .../blackbox/ProbingStep_Factory.java | 27 --- .../blackbox/TestToken_Factory.java | 45 ----- .../blackbox/TestToken_MembersInjector.java | 30 ---- .../TokenModule_DomainNameFactory.java | 27 --- .../TokenModule_ProvideTokenFactory.java | 35 ---- .../blackbox/Token_MembersInjector.java | 31 ---- .../Tokens/WebWhoisToken_Factory.java | 25 --- .../WebWhoisModule_HttpWhoisHostFactory.java | 28 ---- .../WebWhoisModule_HttpWhoisPathFactory.java | 28 ---- .../WebWhoisModule_HttpWhoisPortFactory.java | 26 --- .../WebWhoisModule_HttpsWhoisHostFactory.java | 29 ---- .../WebWhoisModule_HttpsWhoisPathFactory.java | 29 ---- .../WebWhoisModule_HttpsWhoisPortFactory.java | 26 --- ...sModule_ProvideHttpClientCodecFactory.java | 31 ---- ...le_ProvideHttpObjectAggregatorFactory.java | 31 ---- ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ---- ...oisModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ------ ...isModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ------ ...WhoisModule_ProvideSslProviderFactory.java | 30 ---- ...viderHttpWhoisHandlerProvidersFactory.java | 58 ------- ...iderHttpsWhoisHandlerProvidersFactory.java | 75 --------- .../blackbox/WebWhoisToken_Factory.java | 25 --- .../handlers/ActionHandler_Factory.java | 25 --- .../handlers/RedirectHandler_Factory.java | 25 --- .../SslClientInitializer_Factory.java | 35 ---- .../handlers/WebWhoIsHandler_Factory.java | 25 --- .../WebWhoisActionHandler_Factory.java | 25 --- .../DaggerProberModule_ProberComponent.java | 155 ------------------ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...odule_ProvidePortToProtocolMapFactory.java | 43 ----- .../TokenModule_DomainNameFactory.java | 27 --- .../TokenModule_ProvideTokenFactory.java | 35 ---- ...sModule_ProvideHttpClientCodecFactory.java | 31 ---- ...le_ProvideHttpObjectAggregatorFactory.java | 31 ---- ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 54 ------ ...dule_ProvideHttpsWhoisProtocolFactory.java | 54 ------ ...WhoisModule_ProvideSslProviderFactory.java | 30 ---- ...viderHttpWhoisHandlerProvidersFactory.java | 58 ------- ...iderHttpsWhoisHandlerProvidersFactory.java | 75 --------- .../DaggerProberModule_ProberComponent.java | 154 ----------------- .../DaggerTestModule_TestComponent.java | 46 ------ ...berModule_ProvideHttpWhoisPortFactory.java | 29 ---- ...erModule_ProvideHttpsWhoisPortFactory.java | 29 ---- ...odule_ProvidePortToProtocolMapFactory.java | 42 ----- .../blackbox/TestHandler_Factory.java | 25 --- .../TestModule_ProvideHandlersFactory.java | 38 ----- .../TestProtocol_MembersInjector.java | 36 ---- .../TokenModule_DomainNameFactory.java | 27 --- .../TokenModule_ProvideTokenFactory.java | 35 ---- ...sModule_ProvideHttpClientCodecFactory.java | 31 ---- ...le_ProvideHttpObjectAggregatorFactory.java | 31 ---- ...oisModule_ProvideHttpWhoisHostFactory.java | 32 ---- ...odule_ProvideHttpWhoisProtocolFactory.java | 53 ------ ...dule_ProvideHttpsWhoisProtocolFactory.java | 53 ------ ...WhoisModule_ProvideSslProviderFactory.java | 30 ---- ...viderHttpWhoisHandlerProvidersFactory.java | 58 ------- ...iderHttpsWhoisHandlerProvidersFactory.java | 75 --------- 72 files changed, 3018 deletions(-) delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java delete mode 100644 prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java deleted file mode 100644 index 8a727c63bbb..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ActionHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ActionHandler_Factory implements Factory { - private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); - - @Override - public ActionHandler get() { - return new ActionHandler(); - } - - public static ActionHandler_Factory create() { - return INSTANCE; - } - - public static ActionHandler newActionHandler() { - return new ActionHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java deleted file mode 100644 index 39af08b1e60..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java +++ /dev/null @@ -1,154 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { - private final ProberModule proberModule; - - private Provider provideHttpWhoisPortProvider; - - private Provider provideHttpWhoisHostProvider; - - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider provideHttpsWhoisPortProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerProberModule_ProberComponent( - ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { - this.proberModule = proberModuleParam; - initialize(proberModuleParam, webWhoisModuleParam); - } - - public static Builder builder() { - return new Builder(); - } - - public static ProberModule.ProberComponent create() { - return new Builder().build(); - } - - private Set getSetOfProtocol() { - return ImmutableSet.of( - provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); - } - - private WebWhoisToken getWebWhoisToken() { - return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); - } - - @SuppressWarnings("unchecked") - private void initialize( - final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { - this.provideHttpWhoisPortProvider = - ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); - this.provideHttpWhoisHostProvider = - WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - provideHttpWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpWhoisHandlerProvidersProvider)); - this.provideHttpsWhoisPortProvider = - ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - provideHttpsWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public ImmutableMap providePortToProtocolMap() { - return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( - proberModule, getSetOfProtocol()); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); - } - - public static final class Builder { - private ProberModule proberModule; - - private WebWhoisModule webWhoisModule; - - private Builder() {} - - public Builder proberModule(ProberModule proberModule) { - this.proberModule = Preconditions.checkNotNull(proberModule); - return this; - } - - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public ProberModule.ProberComponent build() { - if (proberModule == null) { - this.proberModule = new ProberModule(); - } - if (webWhoisModule == null) { - this.webWhoisModule = new WebWhoisModule(); - } - return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); - } - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java deleted file mode 100644 index ba272c4730a..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/DaggerWebWhoisModule_WebWhoisComponent.java +++ /dev/null @@ -1,119 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerWebWhoisModule_WebWhoisComponent - implements WebWhoisModule.WebWhoisComponent { - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerWebWhoisModule_WebWhoisComponent() { - - initialize(); - } - - public static Builder builder() { - return new Builder(); - } - - public static WebWhoisModule.WebWhoisComponent create() { - return new Builder().build(); - } - - @SuppressWarnings("unchecked") - private void initialize() { - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - WebWhoisModule_HttpWhoisPortFactory.create(), - WebWhoisModule_HttpWhoisHostFactory.create(), - providerHttpWhoisHandlerProvidersProvider)); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - WebWhoisModule_HttpsWhoisPortFactory.create(), - WebWhoisModule_HttpsWhoisHostFactory.create(), - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public Protocol provideHttpWhoisProtocol() { - return provideHttpWhoisProtocolProvider.get(); - } - - @Override - public Protocol provideHttpsWhoisProtocol() { - return provideHttpsWhoisProtocolProvider.get(); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(); - } - - public static final class Builder { - private Builder() {} - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public WebWhoisModule.WebWhoisComponent build() { - return new DaggerWebWhoisModule_WebWhoisComponent(); - } - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java deleted file mode 100644 index 659d36c8249..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoIsPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoIsPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoIsPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoIsPort(module); - } - - public static ProberModule_ProvideHttpWhoIsPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoIsPortFactory(module); - } - - public static int proxyProvideHttpWhoIsPort(ProberModule instance) { - return instance.provideHttpWhoIsPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index 93f9e4f9f48..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(ProberModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index 4d560ae3c94..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisProtocolFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisProtocol(module); - } - - public static ProberModule_ProvideHttpWhoisProtocolFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisProtocolFactory(module); - } - - public static int proxyProvideHttpWhoisProtocol(ProberModule instance) { - return instance.provideHttpWhoisProtocol(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java deleted file mode 100644 index a49efddd550..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoIsPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoIsPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoIsPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoIsPort(module); - } - - public static ProberModule_ProvideHttpsWhoIsPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoIsPortFactory(module); - } - - public static int proxyProvideHttpsWhoIsPort(ProberModule instance) { - return instance.provideHttpsWhoIsPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index 0aee5faf959..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(ProberModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index faaae10cb72..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisProtocolFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisProtocol(module); - } - - public static ProberModule_ProvideHttpsWhoisProtocolFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisProtocolFactory(module); - } - - public static int proxyProvideHttpsWhoisProtocol(ProberModule instance) { - return instance.provideHttpsWhoisProtocol(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java deleted file mode 100644 index 7ab2e4e9dd9..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableMap; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvidePortToProtocolMapFactory - implements Factory> { - private final ProberModule module; - - private final Provider> protocolSetProvider; - - public ProberModule_ProvidePortToProtocolMapFactory( - ProberModule module, Provider> protocolSetProvider) { - this.module = module; - this.protocolSetProvider = protocolSetProvider; - } - - @Override - public ImmutableMap get() { - return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); - } - - public static ProberModule_ProvidePortToProtocolMapFactory create( - ProberModule module, Provider> protocolSetProvider) { - return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); - } - - public static ImmutableMap proxyProvidePortToProtocolMap( - ProberModule instance, Set protocolSet) { - return Preconditions.checkNotNull( - instance.providePortToProtocolMap(protocolSet), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java deleted file mode 100644 index a8d428b93c2..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStepWeb_Factory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProbingStepWeb_Factory implements Factory { - private final Provider protocolProvider; - - public ProbingStepWeb_Factory(Provider protocolProvider) { - this.protocolProvider = protocolProvider; - } - - @Override - public ProbingStepWeb get() { - return new ProbingStepWeb(protocolProvider.get()); - } - - public static ProbingStepWeb_Factory create(Provider protocolProvider) { - return new ProbingStepWeb_Factory(protocolProvider); - } - - public static ProbingStepWeb newProbingStepWeb(Protocol protocol) { - return new ProbingStepWeb(protocol); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java deleted file mode 100644 index 1e8ba7f6af6..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/ProbingStep_Factory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProbingStep_Factory implements Factory> { - @SuppressWarnings("rawtypes") - private static final ProbingStep_Factory INSTANCE = new ProbingStep_Factory(); - - @Override - public ProbingStep get() { - return new ProbingStep(); - } - - @SuppressWarnings("unchecked") - public static ProbingStep_Factory create() { - return INSTANCE; - } - - public static ProbingStep newProbingStep() { - return new ProbingStep(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java deleted file mode 100644 index fd4bf43308d..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_Factory.java +++ /dev/null @@ -1,45 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestToken_Factory implements Factory { - private final Provider actionHandlerProvider; - - private final Provider domainNameProvider; - - private final Provider protocolProvider; - - public TestToken_Factory( - Provider actionHandlerProvider, - Provider domainNameProvider, - Provider protocolProvider) { - this.actionHandlerProvider = actionHandlerProvider; - this.domainNameProvider = domainNameProvider; - this.protocolProvider = protocolProvider; - } - - @Override - public TestToken get() { - TestToken instance = new TestToken(actionHandlerProvider.get(), domainNameProvider.get()); - TestToken_MembersInjector.injectProtocol(instance, protocolProvider.get()); - return instance; - } - - public static TestToken_Factory create( - Provider actionHandlerProvider, - Provider domainNameProvider, - Provider protocolProvider) { - return new TestToken_Factory(actionHandlerProvider, domainNameProvider, protocolProvider); - } - - public static TestToken newTestToken(ActionHandler actionHandler, String domainName) { - return new TestToken(actionHandler, domainName); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java deleted file mode 100644 index db846ba4a36..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TestToken_MembersInjector.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.MembersInjector; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestToken_MembersInjector implements MembersInjector { - private final Provider protocolProvider; - - public TestToken_MembersInjector(Provider protocolProvider) { - this.protocolProvider = protocolProvider; - } - - public static MembersInjector create(Provider protocolProvider) { - return new TestToken_MembersInjector(protocolProvider); - } - - @Override - public void injectMembers(TestToken instance) { - injectProtocol(instance, protocolProvider.get()); - } - - public static void injectProtocol(TestToken instance, Protocol protocol) { - instance.protocol = protocol; - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java deleted file mode 100644 index 1dc41bf0e16..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_DomainNameFactory implements Factory { - private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); - - @Override - public String get() { - return proxyDomainName(); - } - - public static TokenModule_DomainNameFactory create() { - return INSTANCE; - } - - public static String proxyDomainName() { - return Preconditions.checkNotNull( - TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java deleted file mode 100644 index afc66775c9d..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_ProvideTokenFactory implements Factory { - private final Provider tokenProvider; - - public TokenModule_ProvideTokenFactory(Provider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - @Override - public Token get() { - return proxyProvideToken(tokenProvider.get()); - } - - public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { - return new TokenModule_ProvideTokenFactory(tokenProvider); - } - - public static Token proxyProvideToken(WebWhoisToken token) { - return Preconditions.checkNotNull( - TokenModule.provideToken(token), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java deleted file mode 100644 index feab7f7d227..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Token_MembersInjector.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.MembersInjector; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class Token_MembersInjector implements MembersInjector { - private final Provider actionHandlerProvider; - - public Token_MembersInjector(Provider actionHandlerProvider) { - this.actionHandlerProvider = actionHandlerProvider; - } - - public static MembersInjector create(Provider actionHandlerProvider) { - return new Token_MembersInjector(actionHandlerProvider); - } - - @Override - public void injectMembers(Token instance) { - injectActionHandler(instance, actionHandlerProvider.get()); - } - - public static void injectActionHandler(Object instance, ActionHandler actionHandler) { - ((Token) instance).actionHandler = actionHandler; - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java deleted file mode 100644 index 3d153c08fdb..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/Tokens/WebWhoisToken_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.Tokens; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisToken_Factory implements Factory { - private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); - - @Override - public WebWhoisToken get() { - return new WebWhoisToken(); - } - - public static WebWhoisToken_Factory create() { - return INSTANCE; - } - - public static WebWhoisToken newWebWhoisToken() { - return new WebWhoisToken(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java deleted file mode 100644 index f2f34a674d3..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisHostFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpWhoisHostFactory implements Factory { - private static final WebWhoisModule_HttpWhoisHostFactory INSTANCE = - new WebWhoisModule_HttpWhoisHostFactory(); - - @Override - public String get() { - return proxyHttpWhoisHost(); - } - - public static WebWhoisModule_HttpWhoisHostFactory create() { - return INSTANCE; - } - - public static String proxyHttpWhoisHost() { - return Preconditions.checkNotNull( - WebWhoisModule.httpWhoisHost(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java deleted file mode 100644 index 67ab24c06fd..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPathFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpWhoisPathFactory implements Factory { - private static final WebWhoisModule_HttpWhoisPathFactory INSTANCE = - new WebWhoisModule_HttpWhoisPathFactory(); - - @Override - public String get() { - return proxyHttpWhoisPath(); - } - - public static WebWhoisModule_HttpWhoisPathFactory create() { - return INSTANCE; - } - - public static String proxyHttpWhoisPath() { - return Preconditions.checkNotNull( - WebWhoisModule.httpWhoisPath(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java deleted file mode 100644 index 4a29a990b67..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpWhoisPortFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpWhoisPortFactory implements Factory { - private static final WebWhoisModule_HttpWhoisPortFactory INSTANCE = - new WebWhoisModule_HttpWhoisPortFactory(); - - @Override - public Integer get() { - return proxyHttpWhoisPort(); - } - - public static WebWhoisModule_HttpWhoisPortFactory create() { - return INSTANCE; - } - - public static int proxyHttpWhoisPort() { - return WebWhoisModule.httpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java deleted file mode 100644 index f8a7fae07a8..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisHostFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpsWhoisHostFactory implements Factory { - private static final WebWhoisModule_HttpsWhoisHostFactory INSTANCE = - new WebWhoisModule_HttpsWhoisHostFactory(); - - @Override - public String get() { - return proxyHttpsWhoisHost(); - } - - public static WebWhoisModule_HttpsWhoisHostFactory create() { - return INSTANCE; - } - - public static String proxyHttpsWhoisHost() { - return Preconditions.checkNotNull( - WebWhoisModule.httpsWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java deleted file mode 100644 index 4cabb7b5384..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPathFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpsWhoisPathFactory implements Factory { - private static final WebWhoisModule_HttpsWhoisPathFactory INSTANCE = - new WebWhoisModule_HttpsWhoisPathFactory(); - - @Override - public String get() { - return proxyHttpsWhoisPath(); - } - - public static WebWhoisModule_HttpsWhoisPathFactory create() { - return INSTANCE; - } - - public static String proxyHttpsWhoisPath() { - return Preconditions.checkNotNull( - WebWhoisModule.httpsWhoisPath(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java deleted file mode 100644 index 30f4564213a..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_HttpsWhoisPortFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_HttpsWhoisPortFactory implements Factory { - private static final WebWhoisModule_HttpsWhoisPortFactory INSTANCE = - new WebWhoisModule_HttpsWhoisPortFactory(); - - @Override - public Integer get() { - return proxyHttpsWhoisPort(); - } - - public static WebWhoisModule_HttpsWhoisPortFactory create() { - return INSTANCE; - } - - public static int proxyHttpsWhoisPort() { - return WebWhoisModule.httpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java deleted file mode 100644 index 7c756174314..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpClientCodec; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpClientCodecFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = - new WebWhoisModule_ProvideHttpClientCodecFactory(); - - @Override - public HttpClientCodec get() { - return proxyProvideHttpClientCodec(); - } - - public static WebWhoisModule_ProvideHttpClientCodecFactory create() { - return INSTANCE; - } - - public static HttpClientCodec proxyProvideHttpClientCodec() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpClientCodec(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java deleted file mode 100644 index 20785cde372..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = - new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); - - @Override - public HttpObjectAggregator get() { - return proxyProvideHttpObjectAggregator(); - } - - public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { - return INSTANCE; - } - - public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpObjectAggregator(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java deleted file mode 100644 index 7087ab940bc..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public String get() { - return proxyProvideHttpWhoisHost(module); - } - - public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); - } - - public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { - return Preconditions.checkNotNull( - instance.provideHttpWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index a4aaf24978e..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisPortFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisPortFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static WebWhoisModule_ProvideHttpWhoisPortFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(WebWhoisModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index ed7e62f3a5f..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final Provider httpWhoisPortProvider; - - private final Provider httpWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpWhoisProtocolFactory( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpWhoisPortProvider = httpWhoisPortProvider; - this.httpWhoisHostProvider = httpWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpWhoisProtocol( - httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( - httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpWhoisProtocol( - int httpWhoisPort, - String httpWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index c3d7c6546e5..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisPortFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpsWhoisPortFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static WebWhoisModule_ProvideHttpsWhoisPortFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(WebWhoisModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index 4ab50681eea..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final Provider httpsWhoisPortProvider; - - private final Provider httpsWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpsWhoisPortProvider = httpsWhoisPortProvider; - this.httpsWhoisHostProvider = httpsWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpsWhoisProtocol( - httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpsWhoisProtocol( - int httpsWhoisPort, - String httpsWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java deleted file mode 100644 index 7579cc752cf..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { - private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = - new WebWhoisModule_ProvideSslProviderFactory(); - - @Override - public SslProvider get() { - return proxyProvideSslProvider(); - } - - public static WebWhoisModule_ProvideSslProviderFactory create() { - return INSTANCE; - } - - public static SslProvider proxyProvideSslProvider() { - return Preconditions.checkNotNull( - WebWhoisModule.provideSslProvider(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java deleted file mode 100644 index 37431babcb9..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpWhoisHandlerProviders( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java deleted file mode 100644 index adf393894e8..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider> sslClientInitializerProvider; - - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.sslClientInitializerProvider = sslClientInitializerProvider; - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpsWhoisHandlerProviders( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java deleted file mode 100644 index 6c840214a11..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/WebWhoisToken_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisToken_Factory implements Factory { - private static final WebWhoisToken_Factory INSTANCE = new WebWhoisToken_Factory(); - - @Override - public WebWhoisToken get() { - return new WebWhoisToken(); - } - - public static WebWhoisToken_Factory create() { - return INSTANCE; - } - - public static WebWhoisToken newWebWhoisToken() { - return new WebWhoisToken(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java deleted file mode 100644 index d94df8b392f..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/ActionHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ActionHandler_Factory implements Factory { - private static final ActionHandler_Factory INSTANCE = new ActionHandler_Factory(); - - @Override - public ActionHandler get() { - return new ActionHandler(); - } - - public static ActionHandler_Factory create() { - return INSTANCE; - } - - public static ActionHandler newActionHandler() { - return new ActionHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java deleted file mode 100644 index ddf10cf830b..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/RedirectHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class RedirectHandler_Factory implements Factory { - private static final RedirectHandler_Factory INSTANCE = new RedirectHandler_Factory(); - - @Override - public RedirectHandler get() { - return new RedirectHandler(); - } - - public static RedirectHandler_Factory create() { - return INSTANCE; - } - - public static RedirectHandler newRedirectHandler() { - return new RedirectHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java deleted file mode 100644 index 7fa480f418e..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/SslClientInitializer_Factory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import io.netty.channel.Channel; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class SslClientInitializer_Factory - implements Factory> { - private final Provider sslProvider; - - public SslClientInitializer_Factory(Provider sslProvider) { - this.sslProvider = sslProvider; - } - - @Override - public SslClientInitializer get() { - return new SslClientInitializer(sslProvider.get()); - } - - public static SslClientInitializer_Factory create( - Provider sslProvider) { - return new SslClientInitializer_Factory(sslProvider); - } - - public static SslClientInitializer newSslClientInitializer( - SslProvider sslProvider) { - return new SslClientInitializer(sslProvider); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java deleted file mode 100644 index 26b68fdc09c..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoIsHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoIsHandler_Factory implements Factory { - private static final WebWhoIsHandler_Factory INSTANCE = new WebWhoIsHandler_Factory(); - - @Override - public WebWhoIsHandler get() { - return new WebWhoIsHandler(); - } - - public static WebWhoIsHandler_Factory create() { - return INSTANCE; - } - - public static WebWhoIsHandler newWebWhoIsHandler() { - return new WebWhoIsHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java deleted file mode 100644 index dc008e1a724..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisActionHandler_Factory implements Factory { - private static final WebWhoisActionHandler_Factory INSTANCE = new WebWhoisActionHandler_Factory(); - - @Override - public WebWhoisActionHandler get() { - return new WebWhoisActionHandler(); - } - - public static WebWhoisActionHandler_Factory create() { - return INSTANCE; - } - - public static WebWhoisActionHandler newWebWhoisActionHandler() { - return new WebWhoisActionHandler(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java deleted file mode 100644 index b7971395941..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/DaggerProberModule_ProberComponent.java +++ /dev/null @@ -1,155 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { - private final ProberModule proberModule; - - private Provider provideHttpWhoisPortProvider; - - private Provider provideHttpWhoisHostProvider; - - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider provideHttpsWhoisPortProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerProberModule_ProberComponent( - ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { - this.proberModule = proberModuleParam; - initialize(proberModuleParam, webWhoisModuleParam); - } - - public static Builder builder() { - return new Builder(); - } - - public static ProberModule.ProberComponent create() { - return new Builder().build(); - } - - private Set getSetOfProtocol() { - return ImmutableSet.of( - provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); - } - - private WebWhoisToken getWebWhoisToken() { - return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); - } - - @SuppressWarnings("unchecked") - private void initialize( - final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { - this.provideHttpWhoisPortProvider = - ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); - this.provideHttpWhoisHostProvider = - WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - provideHttpWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpWhoisHandlerProvidersProvider)); - this.provideHttpsWhoisPortProvider = - ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - provideHttpsWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public ImmutableMap providePortToProtocolMap() { - return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( - proberModule, getSetOfProtocol()); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); - } - - public static final class Builder { - private ProberModule proberModule; - - private WebWhoisModule webWhoisModule; - - private Builder() {} - - public Builder proberModule(ProberModule proberModule) { - this.proberModule = Preconditions.checkNotNull(proberModule); - return this; - } - - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public ProberModule.ProberComponent build() { - if (proberModule == null) { - this.proberModule = new ProberModule(); - } - if (webWhoisModule == null) { - this.webWhoisModule = new WebWhoisModule(); - } - return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); - } - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index 955698498db..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(ProberModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index 0b97c8dbb72..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(ProberModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java deleted file mode 100644 index e0597aa25f5..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/ProberModule_ProvidePortToProtocolMapFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableMap; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvidePortToProtocolMapFactory - implements Factory> { - private final ProberModule module; - - private final Provider> protocolSetProvider; - - public ProberModule_ProvidePortToProtocolMapFactory( - ProberModule module, Provider> protocolSetProvider) { - this.module = module; - this.protocolSetProvider = protocolSetProvider; - } - - @Override - public ImmutableMap get() { - return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); - } - - public static ProberModule_ProvidePortToProtocolMapFactory create( - ProberModule module, Provider> protocolSetProvider) { - return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); - } - - public static ImmutableMap proxyProvidePortToProtocolMap( - ProberModule instance, Set protocolSet) { - return Preconditions.checkNotNull( - instance.providePortToProtocolMap(protocolSet), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java deleted file mode 100644 index 20e2ca11502..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_DomainNameFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_DomainNameFactory implements Factory { - private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); - - @Override - public String get() { - return proxyDomainName(); - } - - public static TokenModule_DomainNameFactory create() { - return INSTANCE; - } - - public static String proxyDomainName() { - return Preconditions.checkNotNull( - TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java deleted file mode 100644 index e6628332802..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/TokenModule_ProvideTokenFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_ProvideTokenFactory implements Factory { - private final Provider tokenProvider; - - public TokenModule_ProvideTokenFactory(Provider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - @Override - public Token get() { - return proxyProvideToken(tokenProvider.get()); - } - - public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { - return new TokenModule_ProvideTokenFactory(tokenProvider); - } - - public static Token proxyProvideToken(WebWhoisToken token) { - return Preconditions.checkNotNull( - TokenModule.provideToken(token), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java deleted file mode 100644 index 31710bed6eb..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpClientCodecFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpClientCodec; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpClientCodecFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = - new WebWhoisModule_ProvideHttpClientCodecFactory(); - - @Override - public HttpClientCodec get() { - return proxyProvideHttpClientCodec(); - } - - public static WebWhoisModule_ProvideHttpClientCodecFactory create() { - return INSTANCE; - } - - public static HttpClientCodec proxyProvideHttpClientCodec() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpClientCodec(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java deleted file mode 100644 index b69df1a2f7d..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = - new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); - - @Override - public HttpObjectAggregator get() { - return proxyProvideHttpObjectAggregator(); - } - - public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { - return INSTANCE; - } - - public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpObjectAggregator(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java deleted file mode 100644 index bacebd82f49..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisHostFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public String get() { - return proxyProvideHttpWhoisHost(module); - } - - public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); - } - - public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { - return Preconditions.checkNotNull( - instance.provideHttpWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index 0d098288569..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final Provider httpWhoisPortProvider; - - private final Provider httpWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpWhoisProtocolFactory( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpWhoisPortProvider = httpWhoisPortProvider; - this.httpWhoisHostProvider = httpWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpWhoisProtocol( - httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( - httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpWhoisProtocol( - int httpWhoisPort, - String httpWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index c40cde16709..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final Provider httpsWhoisPortProvider; - - private final Provider httpsWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpsWhoisPortProvider = httpsWhoisPortProvider; - this.httpsWhoisHostProvider = httpsWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpsWhoisProtocol( - httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpsWhoisProtocol( - int httpsWhoisPort, - String httpsWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java deleted file mode 100644 index 208d9c7212e..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProvideSslProviderFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { - private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = - new WebWhoisModule_ProvideSslProviderFactory(); - - @Override - public SslProvider get() { - return proxyProvideSslProvider(); - } - - public static WebWhoisModule_ProvideSslProviderFactory create() { - return INSTANCE; - } - - public static SslProvider proxyProvideSslProvider() { - return Preconditions.checkNotNull( - WebWhoisModule.provideSslProvider(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java deleted file mode 100644 index 81eb6efc487..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpWhoisHandlerProviders( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java deleted file mode 100644 index e18a43dd7a8..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/modules/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -package google.registry.monitoring.blackbox.modules; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider> sslClientInitializerProvider; - - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.sslClientInitializerProvider = sslClientInitializerProvider; - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpsWhoisHandlerProviders( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java deleted file mode 100644 index 39af08b1e60..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerProberModule_ProberComponent.java +++ /dev/null @@ -1,154 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import dagger.internal.DoubleCheck; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer_Factory; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler_Factory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerProberModule_ProberComponent implements ProberModule.ProberComponent { - private final ProberModule proberModule; - - private Provider provideHttpWhoisPortProvider; - - private Provider provideHttpWhoisHostProvider; - - private Provider>> - providerHttpWhoisHandlerProvidersProvider; - - private Provider provideHttpWhoisProtocolProvider; - - private Provider provideHttpsWhoisPortProvider; - - private Provider> sslClientInitializerProvider; - - private Provider>> - providerHttpsWhoisHandlerProvidersProvider; - - private Provider provideHttpsWhoisProtocolProvider; - - private DaggerProberModule_ProberComponent( - ProberModule proberModuleParam, WebWhoisModule webWhoisModuleParam) { - this.proberModule = proberModuleParam; - initialize(proberModuleParam, webWhoisModuleParam); - } - - public static Builder builder() { - return new Builder(); - } - - public static ProberModule.ProberComponent create() { - return new Builder().build(); - } - - private Set getSetOfProtocol() { - return ImmutableSet.of( - provideHttpWhoisProtocolProvider.get(), provideHttpsWhoisProtocolProvider.get()); - } - - private WebWhoisToken getWebWhoisToken() { - return new WebWhoisToken(TokenModule_DomainNameFactory.proxyDomainName()); - } - - @SuppressWarnings("unchecked") - private void initialize( - final ProberModule proberModuleParam, final WebWhoisModule webWhoisModuleParam) { - this.provideHttpWhoisPortProvider = - ProberModule_ProvideHttpWhoisPortFactory.create(proberModuleParam); - this.provideHttpWhoisHostProvider = - WebWhoisModule_ProvideHttpWhoisHostFactory.create(webWhoisModuleParam); - this.providerHttpWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.create( - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpWhoisProtocolFactory.create( - provideHttpWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpWhoisHandlerProvidersProvider)); - this.provideHttpsWhoisPortProvider = - ProberModule_ProvideHttpsWhoisPortFactory.create(proberModuleParam); - this.sslClientInitializerProvider = - DoubleCheck.provider( - (Provider) - SslClientInitializer_Factory.create( - WebWhoisModule_ProvideSslProviderFactory.create())); - this.providerHttpsWhoisHandlerProvidersProvider = - WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.create( - sslClientInitializerProvider, - WebWhoisModule_ProvideHttpClientCodecFactory.create(), - WebWhoisModule_ProvideHttpObjectAggregatorFactory.create(), - WebWhoisActionHandler_Factory.create()); - this.provideHttpsWhoisProtocolProvider = - DoubleCheck.provider( - WebWhoisModule_ProvideHttpsWhoisProtocolFactory.create( - provideHttpsWhoisPortProvider, - provideHttpWhoisHostProvider, - providerHttpsWhoisHandlerProvidersProvider)); - } - - @Override - public ImmutableMap providePortToProtocolMap() { - return ProberModule_ProvidePortToProtocolMapFactory.proxyProvidePortToProtocolMap( - proberModule, getSetOfProtocol()); - } - - @Override - public Token provideToken() { - return TokenModule_ProvideTokenFactory.proxyProvideToken(getWebWhoisToken()); - } - - public static final class Builder { - private ProberModule proberModule; - - private WebWhoisModule webWhoisModule; - - private Builder() {} - - public Builder proberModule(ProberModule proberModule) { - this.proberModule = Preconditions.checkNotNull(proberModule); - return this; - } - - public Builder webWhoisModule(WebWhoisModule webWhoisModule) { - this.webWhoisModule = Preconditions.checkNotNull(webWhoisModule); - return this; - } - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder tokenModule(TokenModule tokenModule) { - Preconditions.checkNotNull(tokenModule); - return this; - } - - public ProberModule.ProberComponent build() { - if (proberModule == null) { - this.proberModule = new ProberModule(); - } - if (webWhoisModule == null) { - this.webWhoisModule = new WebWhoisModule(); - } - return new DaggerProberModule_ProberComponent(proberModule, webWhoisModule); - } - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java deleted file mode 100644 index 45032a9c7ba..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/DaggerTestModule_TestComponent.java +++ /dev/null @@ -1,46 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class DaggerTestModule_TestComponent implements TestModule.TestComponent { - private DaggerTestModule_TestComponent() {} - - public static Builder builder() { - return new Builder(); - } - - public static TestModule.TestComponent create() { - return new Builder().build(); - } - - @Override - public ImmutableList> provideHandlers() { - return TestModule_ProvideHandlersFactory.proxyProvideHandlers(TestHandler_Factory.create()); - } - - public static final class Builder { - private Builder() {} - - /** - * @deprecated This module is declared, but an instance is not used in the component. This - * method is a no-op. For more, see https://google.github.io/dagger/unused-modules. - */ - @Deprecated - public Builder testModule(TestModule testModule) { - Preconditions.checkNotNull(testModule); - return this; - } - - public TestModule.TestComponent build() { - return new DaggerTestModule_TestComponent(); - } - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java deleted file mode 100644 index 93f9e4f9f48..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpWhoisPort(module); - } - - public static ProberModule_ProvideHttpWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpWhoisPortFactory(module); - } - - public static int proxyProvideHttpWhoisPort(ProberModule instance) { - return instance.provideHttpWhoisPort(); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java deleted file mode 100644 index 0aee5faf959..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvideHttpsWhoisPortFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvideHttpsWhoisPortFactory implements Factory { - private final ProberModule module; - - public ProberModule_ProvideHttpsWhoisPortFactory(ProberModule module) { - this.module = module; - } - - @Override - public Integer get() { - return proxyProvideHttpsWhoisPort(module); - } - - public static ProberModule_ProvideHttpsWhoisPortFactory create(ProberModule module) { - return new ProberModule_ProvideHttpsWhoisPortFactory(module); - } - - public static int proxyProvideHttpsWhoisPort(ProberModule instance) { - return instance.provideHttpsWhoisPort(); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java deleted file mode 100644 index 7ab2e4e9dd9..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/ProberModule_ProvidePortToProtocolMapFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableMap; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import java.util.Set; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class ProberModule_ProvidePortToProtocolMapFactory - implements Factory> { - private final ProberModule module; - - private final Provider> protocolSetProvider; - - public ProberModule_ProvidePortToProtocolMapFactory( - ProberModule module, Provider> protocolSetProvider) { - this.module = module; - this.protocolSetProvider = protocolSetProvider; - } - - @Override - public ImmutableMap get() { - return proxyProvidePortToProtocolMap(module, protocolSetProvider.get()); - } - - public static ProberModule_ProvidePortToProtocolMapFactory create( - ProberModule module, Provider> protocolSetProvider) { - return new ProberModule_ProvidePortToProtocolMapFactory(module, protocolSetProvider); - } - - public static ImmutableMap proxyProvidePortToProtocolMap( - ProberModule instance, Set protocolSet) { - return Preconditions.checkNotNull( - instance.providePortToProtocolMap(protocolSet), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java deleted file mode 100644 index 50616d20699..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestHandler_Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestHandler_Factory implements Factory { - private static final TestHandler_Factory INSTANCE = new TestHandler_Factory(); - - @Override - public TestHandler get() { - return new TestHandler(); - } - - public static TestHandler_Factory create() { - return INSTANCE; - } - - public static TestHandler newTestHandler() { - return new TestHandler(); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java deleted file mode 100644 index 79e40ee2d4a..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestModule_ProvideHandlersFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestModule_ProvideHandlersFactory - implements Factory>> { - private final Provider testHandlerProvider; - - public TestModule_ProvideHandlersFactory(Provider testHandlerProvider) { - this.testHandlerProvider = testHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProvideHandlers(testHandlerProvider); - } - - public static TestModule_ProvideHandlersFactory create( - Provider testHandlerProvider) { - return new TestModule_ProvideHandlersFactory(testHandlerProvider); - } - - public static ImmutableList> proxyProvideHandlers( - Provider testHandlerProvider) { - return Preconditions.checkNotNull( - TestModule.provideHandlers(testHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java deleted file mode 100644 index 75b788ec968..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TestProtocol_MembersInjector.java +++ /dev/null @@ -1,36 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.MembersInjector; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TestProtocol_MembersInjector implements MembersInjector { - private final Provider>> - handlerProvidersProvider; - - public TestProtocol_MembersInjector( - Provider>> handlerProvidersProvider) { - this.handlerProvidersProvider = handlerProvidersProvider; - } - - public static MembersInjector create( - Provider>> handlerProvidersProvider) { - return new TestProtocol_MembersInjector(handlerProvidersProvider); - } - - @Override - public void injectMembers(TestProtocol instance) { - injectTestProtocolHandlers(instance, handlerProvidersProvider.get()); - } - - public static void injectTestProtocolHandlers( - TestProtocol instance, ImmutableList> handlerProviders) { - instance.TestProtocolHandlers(handlerProviders); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java deleted file mode 100644 index 1dc41bf0e16..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_DomainNameFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_DomainNameFactory implements Factory { - private static final TokenModule_DomainNameFactory INSTANCE = new TokenModule_DomainNameFactory(); - - @Override - public String get() { - return proxyDomainName(); - } - - public static TokenModule_DomainNameFactory create() { - return INSTANCE; - } - - public static String proxyDomainName() { - return Preconditions.checkNotNull( - TokenModule.domainName(), "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java deleted file mode 100644 index afc66775c9d..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/TokenModule_ProvideTokenFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class TokenModule_ProvideTokenFactory implements Factory { - private final Provider tokenProvider; - - public TokenModule_ProvideTokenFactory(Provider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - @Override - public Token get() { - return proxyProvideToken(tokenProvider.get()); - } - - public static TokenModule_ProvideTokenFactory create(Provider tokenProvider) { - return new TokenModule_ProvideTokenFactory(tokenProvider); - } - - public static Token proxyProvideToken(WebWhoisToken token) { - return Preconditions.checkNotNull( - TokenModule.provideToken(token), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java deleted file mode 100644 index 7c756174314..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpClientCodecFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpClientCodec; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpClientCodecFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpClientCodecFactory INSTANCE = - new WebWhoisModule_ProvideHttpClientCodecFactory(); - - @Override - public HttpClientCodec get() { - return proxyProvideHttpClientCodec(); - } - - public static WebWhoisModule_ProvideHttpClientCodecFactory create() { - return INSTANCE; - } - - public static HttpClientCodec proxyProvideHttpClientCodec() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpClientCodec(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java deleted file mode 100644 index 20785cde372..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpObjectAggregatorFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpObjectAggregatorFactory - implements Factory { - private static final WebWhoisModule_ProvideHttpObjectAggregatorFactory INSTANCE = - new WebWhoisModule_ProvideHttpObjectAggregatorFactory(); - - @Override - public HttpObjectAggregator get() { - return proxyProvideHttpObjectAggregator(); - } - - public static WebWhoisModule_ProvideHttpObjectAggregatorFactory create() { - return INSTANCE; - } - - public static HttpObjectAggregator proxyProvideHttpObjectAggregator() { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpObjectAggregator(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java deleted file mode 100644 index 7087ab940bc..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisHostFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisHostFactory implements Factory { - private final WebWhoisModule module; - - public WebWhoisModule_ProvideHttpWhoisHostFactory(WebWhoisModule module) { - this.module = module; - } - - @Override - public String get() { - return proxyProvideHttpWhoisHost(module); - } - - public static WebWhoisModule_ProvideHttpWhoisHostFactory create(WebWhoisModule module) { - return new WebWhoisModule_ProvideHttpWhoisHostFactory(module); - } - - public static String proxyProvideHttpWhoisHost(WebWhoisModule instance) { - return Preconditions.checkNotNull( - instance.provideHttpWhoisHost(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java deleted file mode 100644 index ed7e62f3a5f..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpWhoisProtocolFactory implements Factory { - private final Provider httpWhoisPortProvider; - - private final Provider httpWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpWhoisProtocolFactory( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpWhoisPortProvider = httpWhoisPortProvider; - this.httpWhoisHostProvider = httpWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpWhoisProtocol( - httpWhoisPortProvider.get(), httpWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpWhoisProtocolFactory create( - Provider httpWhoisPortProvider, - Provider httpWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpWhoisProtocolFactory( - httpWhoisPortProvider, httpWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpWhoisProtocol( - int httpWhoisPort, - String httpWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpWhoisProtocol(httpWhoisPort, httpWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java deleted file mode 100644 index 4ab50681eea..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideHttpsWhoisProtocolFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideHttpsWhoisProtocolFactory implements Factory { - private final Provider httpsWhoisPortProvider; - - private final Provider httpsWhoisHostProvider; - - private final Provider>> - handlerProvidersProvider; - - public WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - this.httpsWhoisPortProvider = httpsWhoisPortProvider; - this.httpsWhoisHostProvider = httpsWhoisHostProvider; - this.handlerProvidersProvider = handlerProvidersProvider; - } - - @Override - public Protocol get() { - return proxyProvideHttpsWhoisProtocol( - httpsWhoisPortProvider.get(), httpsWhoisHostProvider.get(), handlerProvidersProvider.get()); - } - - public static WebWhoisModule_ProvideHttpsWhoisProtocolFactory create( - Provider httpsWhoisPortProvider, - Provider httpsWhoisHostProvider, - Provider>> handlerProvidersProvider) { - return new WebWhoisModule_ProvideHttpsWhoisProtocolFactory( - httpsWhoisPortProvider, httpsWhoisHostProvider, handlerProvidersProvider); - } - - public static Protocol proxyProvideHttpsWhoisProtocol( - int httpsWhoisPort, - String httpsWhoisHost, - ImmutableList> handlerProviders) { - return Preconditions.checkNotNull( - WebWhoisModule.provideHttpsWhoisProtocol(httpsWhoisPort, httpsWhoisHost, handlerProviders), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java deleted file mode 100644 index 7579cc752cf..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProvideSslProviderFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package google.registry.monitoring.blackbox; - -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import io.netty.handler.ssl.SslProvider; -import javax.annotation.Generated; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProvideSslProviderFactory implements Factory { - private static final WebWhoisModule_ProvideSslProviderFactory INSTANCE = - new WebWhoisModule_ProvideSslProviderFactory(); - - @Override - public SslProvider get() { - return proxyProvideSslProvider(); - } - - public static WebWhoisModule_ProvideSslProviderFactory create() { - return INSTANCE; - } - - public static SslProvider proxyProvideSslProvider() { - return Preconditions.checkNotNull( - WebWhoisModule.provideSslProvider(), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java deleted file mode 100644 index 37431babcb9..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory create( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpWhoisHandlerProvidersFactory( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpWhoisHandlerProviders( - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpWhoisHandlerProviders( - httpClientCodecProvider, httpObjectAggregatorProvider, webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} diff --git a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java b/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java deleted file mode 100644 index adf393894e8..00000000000 --- a/prober/out/test/classes/generated_tests/google/registry/monitoring/blackbox/WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import dagger.internal.Factory; -import dagger.internal.Preconditions; -import google.registry.monitoring.blackbox.handlers.SslClientInitializer; -import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated( - value = "dagger.internal.codegen.ComponentProcessor", - comments = "https://google.github.io/dagger" -) -public final class WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory - implements Factory>> { - private final Provider> sslClientInitializerProvider; - - private final Provider httpClientCodecProvider; - - private final Provider httpObjectAggregatorProvider; - - private final Provider webWhoisActionHandlerProvider; - - public WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - this.sslClientInitializerProvider = sslClientInitializerProvider; - this.httpClientCodecProvider = httpClientCodecProvider; - this.httpObjectAggregatorProvider = httpObjectAggregatorProvider; - this.webWhoisActionHandlerProvider = webWhoisActionHandlerProvider; - } - - @Override - public ImmutableList> get() { - return proxyProviderHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory create( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return new WebWhoisModule_ProviderHttpsWhoisHandlerProvidersFactory( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider); - } - - public static ImmutableList> - proxyProviderHttpsWhoisHandlerProviders( - Provider> sslClientInitializerProvider, - Provider httpClientCodecProvider, - Provider httpObjectAggregatorProvider, - Provider webWhoisActionHandlerProvider) { - return Preconditions.checkNotNull( - WebWhoisModule.providerHttpsWhoisHandlerProviders( - sslClientInitializerProvider, - httpClientCodecProvider, - httpObjectAggregatorProvider, - webWhoisActionHandlerProvider), - "Cannot return null from a non-@Nullable @Provides method"); - } -} From 7e3e5a040e0bc0939590a9b428a74a22043a471d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:30:57 -0400 Subject: [PATCH 151/337] Final Changes in .gitignore --- prober/.gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index c86568e7672..89f9ac04aac 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From 86112220652a9369099196b85b15dd470450da76 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 16:56:54 -0400 Subject: [PATCH 152/337] Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class --- .../monitoring/blackbox/ProbingAction.java | 156 +++++++++++ .../monitoring/blackbox/Protocol.java | 16 +- .../handlers/SslClientInitializer.java | 53 +--- .../handlers/WebWhoisActionHandler.java | 184 ++++--------- .../monitoring/blackbox/TestUtils.java | 143 +++++----- .../blackbox/handlers/NettyRule.java | 96 +++---- .../blackbox/handlers/RedirectHandler.java | 5 + .../handlers/SslClientInitializerTest.java | 51 ++-- .../handlers/SslInitializerTestUtils.java | 3 +- .../handlers/WebWhoisActionHandlerTest.java | 247 ++++++++---------- 10 files changed, 485 insertions(+), 469 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java new file mode 100644 index 00000000000..6fbcadaf999 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -0,0 +1,156 @@ +// 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.monitoring.blackbox; + +import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import io.netty.util.AttributeKey; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; +import java.util.concurrent.Callable; +import javax.inject.Provider; + +/** + *Class that represents given action in sequence of probing + * + */ + + +public abstract class ProbingAction implements Callable { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Attribute Key that links channel to its {@link ProbingAction}*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** {@link ActionHandler} Associated with this {@link ProbingAction}*/ + private ActionHandler actionHandler; + + + /** + * The requisite instance of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline + */ + public ActionHandler actionHandler() { + return actionHandler; + } + + + /** {@link Timer} that rate limits probing*/ + private static final Timer timer = new HashedWheelTimer(); + + + /** actual {@link Duration} of this delay*/ + public abstract Duration delay(); + + /** message to send to server */ + public abstract O outboundMessage(); + + /** + * @return {@link Channel} object that represents connection between prober client and server + */ + public abstract Channel channel(); + + /** + * @return The {@link Protocol} instance that represents action to be tested by this part in sequences + */ + public abstract Protocol protocol(); + + /** + * + * @return {@link Builder} that lets us build a new ProbingAction by customizing abstract methods + */ + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** + * The method that calls the {@link ActionHandler} to send a message down the channel pipeline + * @return future that denotes when the action has been successfully performed + */ + + @Override + public ChannelFuture call() { + + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch(ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + } + + + + + ChannelPromise finished = channel().newPromise(); + + //Every specified time frame by delay(), we perform the next action in our sequence + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + ChannelFuture channelFuture = actionHandler().apply(outboundMessage()); + + channelFuture.addListeners( + future -> actionHandler().resetFuture(), + future -> finished.setSuccess()); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + + return finished; + } + + public abstract static class Builder, P extends ProbingAction> { + + public abstract B delay(Duration value); + + public abstract B outboundMessage(O value); + + public abstract B protocol(Protocol value); + + abstract P autoBuild(); + + public P build() { + P probingAction = autoBuild(); + probingAction.protocol().probingAction(probingAction); + return probingAction; + } + } + /** + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified + */ + static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); + } + } + +} + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 50a1d90a12c..913b7d7627e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -28,6 +28,8 @@ @AutoValue public abstract class Protocol { + public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + /** * Default names associated with each protocol */ @@ -38,6 +40,7 @@ public abstract class Protocol { private String host; private String path = ""; + private ProbingAction probingAction; /** Setter method for Protocol's host*/ public Protocol host(String host) { @@ -61,6 +64,17 @@ public String path() { return path; } + /** Setter method for Protocol's ProbingAction parent*/ + public Protocol probingAction(ProbingAction probingAction) { + this.probingAction = probingAction; + return this; + } + + /** Getter method for Protocol's path*/ + public ProbingAction probingAction() { + return probingAction; + } + /** If connection associated with Protocol is persistent, which is only EPP */ public boolean persistentConnection() { return name() == EPP_PROTOCOL_NAME; @@ -78,7 +92,7 @@ public boolean persistentConnection() { public abstract Builder toBuilder(); - public static Protocol.Builder builder() { + public static Builder builder() { return new AutoValue_Protocol.Builder(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index c62668b19b2..eeecb468fce 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -15,11 +15,12 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; + import google.registry.monitoring.blackbox.Protocol; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler.Sharable; @@ -28,9 +29,8 @@ import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslHandler; import io.netty.handler.ssl.SslProvider; -import java.security.PrivateKey; import java.security.cert.X509Certificate; -import java.util.function.Supplier; +import javax.inject.Inject; import javax.inject.Singleton; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; @@ -38,9 +38,6 @@ /** * Adds a client side SSL handler to the channel pipeline. * - *

Code is close to unchanged from {@link SslClientInitializer}

in proxy, but is modified - * for revised overall structure of connections, and to accomdate EPP connections

- * *

This must be the first handler provided for any handler provider list, if it is * provided. The type parameter {@code C} is needed so that unit tests can construct this handler * that works with {@link EmbeddedChannel}; @@ -53,59 +50,30 @@ public class SslClientInitializer extends ChannelInitializer< private final SslProvider sslProvider; private final X509Certificate[] trustedCertificates; - private final Supplier privateKeySupplier; - private final Supplier certificateSupplier; - + @Inject public SslClientInitializer(SslProvider sslProvider) { // null uses the system default trust store. - //Used for WebWhois, so we don't care about privateKey and certificates, setting them to null - this(sslProvider, null, null, null); - } - - public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, - Supplier certificateSupplier) { - //We use the default trust store here as well, setting trustCertificates to null - this(sslProvider, null, privateKeySupplier, certificateSupplier); + this(sslProvider, null); } @VisibleForTesting SslClientInitializer(SslProvider sslProvider, X509Certificate[] trustCertificates) { - this(sslProvider, trustCertificates, null, null); - } - - private SslClientInitializer( - SslProvider sslProvider, - X509Certificate[] trustCertificates, - Supplier privateKeySupplier, - Supplier certificateSupplier) { logger.atInfo().log("Client SSL Provider: %s", sslProvider); - this.sslProvider = sslProvider; this.trustedCertificates = trustCertificates; - this.privateKeySupplier = privateKeySupplier; - this.certificateSupplier = certificateSupplier; } @Override protected void initChannel(C channel) throws Exception { Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - String host = channel.attr(REMOTE_ADDRESS_KEY).get(); - - //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); - SslContextBuilder sslContextBuilder = + SslHandler sslHandler = SslContextBuilder.forClient() .sslProvider(sslProvider) - .trustManager(trustedCertificates); - if (privateKeySupplier != null && certificateSupplier != null) { - sslContextBuilder = sslContextBuilder - .keyManager(privateKeySupplier.get(), certificateSupplier.get()); - } - - SslHandler sslHandler = sslContextBuilder - .build() - .newHandler(channel.alloc(), host, protocol.port()); + .trustManager(trustedCertificates) + .build() + .newHandler(channel.alloc(), protocol.host(), protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); @@ -116,4 +84,3 @@ protected void initChannel(C channel) throws Exception { channel.pipeline().addLast(sslHandler); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index c0f7ce8ae78..1a1664a3c3c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. @@ -14,174 +14,92 @@ package google.registry.monitoring.blackbox.handlers; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import java.net.MalformedURLException; import java.net.URL; import javax.inject.Inject; -import org.joda.time.Duration; -/** - * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence - * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response - * implies a redirection it follows the redirection until either an Error Response is received, or - * {@link HttpResponseStatus.OK} is received

- */ -public class WebWhoisActionHandler extends ActionHandler { +public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** - * {@link Bootstrap} necessary for remaking connection on redirect response. - */ - private final Bootstrap bootstrap; - - /** - * {@link Protocol} for when redirected to http endpoint. - */ - private final Protocol httpWhoisProtocol; - - /** - * {@link Protocol} for when redirected to https endpoint. - */ - private final Protocol httpsWhoisProtocol; - - /** - * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. - */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } - + public WebWhoisActionHandler() {} - /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, - * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a - * response indicating a Failure, or receives a redirection response, where it follows the - * redirects until receiving one of the previous three responses. - */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { - - HttpResponseMessage response = (HttpResponseMessage) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpResponse response) throws Exception{ + if (response.status() == HttpResponseStatus.OK) { + logger.atInfo().log("Recieved Successful HttpResponseStatus"); + finished.setSuccess(); + System.out.println(response); - if (response.status().equals(HttpResponseStatus.OK)) { - logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - - //On success, we always pass message to ActionHandler's channelRead0 method. - super.channelRead0(ctx, msg); - - } else if (response.headers().get("location") != null) { + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { //Obtain url to be redirected to - URL url; - try { - url = new URL(response.headers().get("Location")); - } catch (MalformedURLException e) { - //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException( - "Redirected Location was invalid. Given Location was: " + response.headers() - .get("Location")); - } + URL url = new URL(response.headers().get("Location")); + //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); + int newPort = url.getDefaultPort(); - logger.atInfo().log(String - .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, - url.getDefaultPort(), newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); + + + Protocol oldProtocol = ctx.channel().attr(PROTOCOL_KEY).get(); + + //Build new Protocol from new attributes + ProbingAction currentAction = oldProtocol.probingAction(); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException( - "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); - } - - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); - - //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + Protocol newProtocol = Prober.portToProtocolMap.get(newPort).toBuilder().build() + .host(newHost) + .path(newPath); + + //Modify HttpRequest sent to remote host to reflect new path and host + FullHttpRequest httpRequest = ((DefaultFullHttpRequest) currentAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + + + //Create new probingAction that takes in the new Protocol and HttpRequest message + ProbingAction redirectedAction = currentAction., NewChannelAction>toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) .build(); + oldProtocol.probingAction(redirectedAction); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } - - //Once channel is closed, establish new connection to redirected host, and repeat - // same actions + logger.atInfo().log("Successfully Closed Connection"); + + //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell - // ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { - //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); + finished.setFailure(new RuntimeException()); + logger.atWarning().log(String.format("Received Response: %s", response.status())); } } - - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index c0c5831a68c..5d9a8b5a977 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,26 +14,40 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.cookie.ClientCookieEncoder; +import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.ServerCookieEncoder; -/** - * Utility class for various helper methods used in testing. - */ +/** Utility class for various helper methods used in testing. */ public class TestUtils { + public static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -54,73 +68,80 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { return response; } - /** - * Creates HttpResponse given status, redirection location, and other necessary inputs - */ - public static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - return response; + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; } - /** - * Basic outline for {@link Token} instances to be used in tests - */ - abstract static class TestToken extends Token { - - protected String host; - - protected TestToken(String host) { - this.host = host; - } - - @Override - public Token next() { - return this; + public static FullHttpRequest makeEppHttpRequest( + String content, + String host, + String path, + String accessToken, + String sslClientCertificateHash, + String clientAddress, + Cookie... cookies) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "application/epp+xml") + .set("accept", "application/epp+xml") + .set("X-SSL-Certificate", sslClientCertificateHash) + .set("X-Forwarded-For", clientAddress); + if (cookies.length != 0) { + request.headers().set("cookie", ClientCookieEncoder.STRICT.encode(cookies)); } + return request; + } - @Override - public OutboundMessageType modifyMessage(OutboundMessageType message) { - return message; - } + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); + return response; + } - @Override - public String host() { - return host; + public static FullHttpResponse makeEppHttpResponse( + String content, HttpResponseStatus status, Cookie... cookies) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "application/epp+xml"); + for (Cookie cookie : cookies) { + response.headers().add("set-cookie", ServerCookieEncoder.STRICT.encode(cookie)); } - + return response; } /** - * {@link TestToken} instance that creates new channel + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. */ - public static class NewChannelToken extends TestToken { - - public NewChannelToken(String host) { - super(host); + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); } + } - @Override - public Channel channel() { - return null; - } + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); } - /** - * {@link TestToken} instance that passes in existing channel - */ - public static class ExistingChannelToken extends TestToken { - public ExistingChannelToken(Channel channel, String host) { - super(host); - this.channel = channel; - } + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index f51f8c8fd61..399bc9c4c35 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. @@ -16,20 +16,17 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; + import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingActionTest; -import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -41,6 +38,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -51,25 +49,14 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest} - *

+ *

Used in {@link SslClientInitializerTest} */ -public final class NettyRule extends ExternalResource { - +final class NettyRule extends ExternalResource { // All I/O operations are done inside the single thread within this event loop group, which is // different from the main test thread. Therefore synchronizations are required to make sure that // certain I/O activities are finished when assertions are performed. - public NettyRule() { - eventLoopGroup = new NioEventLoopGroup(1); - } - - public NettyRule(EventLoopGroup e) { - eventLoopGroup = e; - } - - private final EventLoopGroup eventLoopGroup; + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); // Handler attached to server's channel to record the request received. private EchoHandler echoHandler; @@ -79,24 +66,32 @@ public NettyRule(EventLoopGroup e) { private Channel channel; - /** - * Sets up a server channel bound to the given local address. - */ - public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { + /** Sets up a server channel bound to the given local address. */ + void setUpServer(LocalAddress localAddress, ChannelHandler handler) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - - new WebWhoisServer(eventLoopGroup, localAddress, - ImmutableList.builder().add(handlers).add(echoHandler).build()); + ChannelInitializer serverInitializer = + new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) { + // Add the given handler + ch.pipeline().addLast(handler); + // Add the "echoHandler" last to log the incoming message and send it back + ch.pipeline().addLast(echoHandler); + } + }; + ServerBootstrap sb = + new ServerBootstrap() + .group(eventLoopGroup) + .channel(LocalServerChannel.class) + .childHandler(serverInitializer); + ChannelFuture unusedFuture = sb.bind(localAddress).syncUninterruptibly(); } - /** - * Sets up a client channel connecting to the give local address. - */ + /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, Protocol protocol, - String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -116,30 +111,20 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol) - .attr(REMOTE_ADDRESS_KEY, host); - + .attr(PROTOCOL_KEY, protocol); channel = b.connect(localAddress).syncUninterruptibly().channel(); } - private void checkReady() { + void checkReady() { checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); } - /** - * Test that custom setup to send message to current server sends right message - */ - public void assertReceivedMessage(String message) throws Exception { - assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); - - } - /** * Test that a message can go through, both inbound and outbound. * - *

The client writes the message to the server, which echos it back and saves the string in - * its promise. The client receives the echo and saves it in its promise. All these activities - * happens in the I/O thread, and this call itself returns immediately. + *

The client writes the message to the server, which echos it back and saves the string in its + * promise. The client receives the echo and saves it in its promise. All these activities happens + * in the I/O thread, and this call itself returns immediately. */ void assertThatMessagesWork() throws Exception { checkReady(); @@ -169,23 +154,21 @@ ThrowableSubject assertThatClientRootCause() { assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); } - /** * A handler that echoes back its inbound message. The message is also saved in a promise for * inspection later. */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { + private static class EchoHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture requestFuture = new CompletableFuture<>(); - public Future getRequestFuture() { + Future getRequestFuture() { return requestFuture; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // In the test we only send messages of type ByteBuf. - assertThat(msg).isInstanceOf(ByteBuf.class); String request = ((ByteBuf) msg).toString(UTF_8); // After the message is written back to the client, fulfill the promise. @@ -193,9 +176,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); } - /** - * Saves any inbound error as the cause of the promise failure. - */ + /** Saves any inbound error as the cause of the promise failure. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ChannelFuture unusedFuture = @@ -203,9 +184,7 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E } } - /** - * A handler that dumps its inbound message to a promise that can be inspected later. - */ + /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture responseFuture = new CompletableFuture<>(); @@ -226,9 +205,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception responseFuture.complete(response); } - /** - * Saves any inbound error into the failure cause of the promise. - */ + /** Saves any inbound error into the failure cause of the promise. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); @@ -245,4 +222,3 @@ private static void writeToChannelAndFlush(Channel channel, String data) { channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java new file mode 100644 index 00000000000..f7af491e39e --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox.handlers; + +public class RedirectHandler { + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 25e5608a100..6725643c48d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -15,7 +15,6 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; @@ -62,14 +61,10 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - /** - * Fake host to test if the SSL engine gets the correct peer host. - */ + /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; - /** - * Fake port to test if the SSL engine gets the correct peer port. - */ + /** Fake port to test if the SSL engine gets the correct peer port. */ private static final int SSL_PORT = 12345; @Rule @@ -82,24 +77,21 @@ public class SslClientInitializerTest { @Parameters(name = "{0}") public static SslProvider[] data() { return OpenSsl.isAvailable() - ? new SslProvider[]{SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[]{SslProvider.JDK}; + ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[] {SslProvider.JDK}; } - /** - * Saves the SNI hostname received by the server, if sent by the client. - */ + /** Saves the SNI hostname received by the server, if sent by the client. */ private String sniHostReceived; - /** - * Fake protocol saved in channel attribute. - */ - private static final Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + /** Fake protocol saved in channel attribute. */ + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .build() + .host(SSL_HOST); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -117,7 +109,6 @@ public void testSuccess_swappedInitializerWithSslHandler() throws Exception { new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); channel.attr(PROTOCOL_KEY).set(PROTOCOL); - channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -147,8 +138,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except nettyRule.setUpServer(localAddress, getServerHandler(ssc.key(), ssc.cert())); SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -174,9 +164,8 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); - - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -203,9 +192,8 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); - - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. @@ -215,4 +203,3 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E assertThat(nettyRule.getChannel().isActive()).isFalse(); } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java index 68b2919141d..7b4aae50106 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -92,4 +92,3 @@ static SSLSession setUpSslChannel( return sslHandler.engine().getSession(); } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 5a0d0908724..001c935d70a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -1,235 +1,208 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; + import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelPromise; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import javax.inject.Provider; +import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@link WebWhoisActionHandler}. - * - *

Attempts to test how well {@link WebWhoisActionHandler} works - * when responding to all possible types of responses

- */ +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; + private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; + private static final String HTTPS_REDIRECT = "https://"; + private static final String REDIRECT_HOST = "www.example.com"; + private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; - private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private final Protocol standardProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( - null, null, null, null))) - .setName("http") - .setPersistentConnection(false) - .setPort(HTTP_PORT) - .build(); + private static final Duration DEFAULT_DURATION = new Duration(0L); private EmbeddedChannel channel; private ActionHandler actionHandler; - private Provider actionHandlerProvider; - private Protocol initialProtocol; - private HttpRequestMessage msg; - - /** - * Creates default protocol with empty list of handlers and specified other inputs - */ - private Protocol createProtocol(String name, int port, boolean persistentConnection) { + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() - .setName(name) - .setPort(port) - .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) - .setPersistentConnection(persistentConnection) - .build(); + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); } - /** - * Initializes new WebWhoisActionHandler - */ - private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { - actionHandler = new WebWhoisActionHandler( - bootstrap, - standardProtocol, - standardProtocol, - messageTemplate - ); - actionHandlerProvider = () -> actionHandler; + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); } - /** - * Sets up testing channel with requisite attributes - */ + /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol) { + setupActionHandler(); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - private Bootstrap makeBootstrap(EventLoopGroup group) { - return new Bootstrap() - .group(group) - .channel(LocalChannel.class); + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group, LocalAddress address) { - WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); } - private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { - msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); - setupActionHandler(bootstrap, msg); - initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; } + @Test - public void testBasic_responseOk() { + public void testSuccess_responseOk() { //setup - setup("", null, true); + Protocol initialProtocol = createProtocol("responseOk", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); - //assesses that we successfully received good response and protocol is unchanged + //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badRequest() { + public void testSuccess_responseBad() { //setup - setup("", null, false); + Protocol initialProtocol = createProtocol("responseBad", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); - FullHttpResponse response = new HttpResponseMessage( - makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(future.isDone()).isTrue(); + assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } - @SuppressWarnings("CheckReturnValue") @Test - public void testBasic_responseFailure_badURL() { + public void testSuccess_redirectCloseChannel() { //setup - setup("", null, false); - setupChannel(initialProtocol); + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, and event is success - assertThat(future.isDone()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_redirect() { - // Sets up EventLoopGroup with 1 thread to be blocking. - EventLoopGroup group = new NioEventLoopGroup(1); - - // Sets up embedded channel. - setup("", makeBootstrap(group), false); - setupChannel(initialProtocol); + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - // Initializes LocalAddress with unique String. - String host = TARGET_HOST + System.currentTimeMillis(); - LocalAddress address = new LocalAddress(host); + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); - // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group, address); + channel.writeInbound(originalResponse); - FullHttpResponse response = - new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + host, true, false)); + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); - //checks that future has not been set to successful or a failure - assertThat(future.isDone()).isFalse(); + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } + } From d310d65c159649a540f41528c23a4b5e985d4451 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 16:58:33 -0400 Subject: [PATCH 153/337] Fixed build.gradle changes requested --- prober/build.gradle | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index fe5e08a62f5..e826fb6c37a 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -5,21 +5,13 @@ createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober dependencies { def deps = rootProject.dependencyMap - - compile deps['com.beust:jcommander'] - compile deps['com.google.api-client:google-api-client'] - compile deps['com.google.apis:google-api-services-cloudkms'] - compile deps['com.google.apis:google-api-services-monitoring'] - compile deps['com.google.apis:google-api-services-storage'] + compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] - compile deps['com.google.http-client:google-http-client'] - compile deps['com.google.monitoring-client:metrics'] - compile deps['com.google.monitoring-client:stackdriver'] compile deps['io.netty:netty-buffer'] compile deps['io.netty:netty-codec-http'] compile deps['io.netty:netty-codec'] @@ -35,10 +27,8 @@ dependencies { runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - - testCompile deps['com.google.monitoring-client:contrib'] + testCompile deps['com.google.truth:truth'] - testCompile deps['org.yaml:snakeyaml'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') From 36ec1f1e1058cdf5025a81a2e16cd3015e54a237 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:04:45 -0400 Subject: [PATCH 154/337] Removed Files irrelevant to current pull request --- .../monitoring/blackbox/ProbingAction.java | 156 ------------ .../handlers/SslClientInitializer.java | 86 ------- .../handlers/WebWhoisActionHandler.java | 105 -------- .../blackbox/Handlers/ActionHandlerTest.java | 85 ------- .../monitoring/blackbox/TestUtils.java | 147 ------------ .../blackbox/handlers/NettyRule.java | 224 ------------------ .../blackbox/handlers/RedirectHandler.java | 5 - .../handlers/SslClientInitializerTest.java | 205 ---------------- .../handlers/SslInitializerTestUtils.java | 94 -------- .../handlers/WebWhoisActionHandlerTest.java | 208 ---------------- 10 files changed, 1315 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java deleted file mode 100644 index 6fbcadaf999..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ /dev/null @@ -1,156 +0,0 @@ -// 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.monitoring.blackbox; - -import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import io.netty.util.AttributeKey; -import java.util.concurrent.TimeUnit; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; -import javax.inject.Provider; - -/** - *Class that represents given action in sequence of probing - * - */ - - -public abstract class ProbingAction implements Callable { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** Attribute Key that links channel to its {@link ProbingAction}*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** {@link ActionHandler} Associated with this {@link ProbingAction}*/ - private ActionHandler actionHandler; - - - /** - * The requisite instance of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline - */ - public ActionHandler actionHandler() { - return actionHandler; - } - - - /** {@link Timer} that rate limits probing*/ - private static final Timer timer = new HashedWheelTimer(); - - - /** actual {@link Duration} of this delay*/ - public abstract Duration delay(); - - /** message to send to server */ - public abstract O outboundMessage(); - - /** - * @return {@link Channel} object that represents connection between prober client and server - */ - public abstract Channel channel(); - - /** - * @return The {@link Protocol} instance that represents action to be tested by this part in sequences - */ - public abstract Protocol protocol(); - - /** - * - * @return {@link Builder} that lets us build a new ProbingAction by customizing abstract methods - */ - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** - * The method that calls the {@link ActionHandler} to send a message down the channel pipeline - * @return future that denotes when the action has been successfully performed - */ - - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch(ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); - } - - - - - ChannelPromise finished = channel().newPromise(); - - //Every specified time frame by delay(), we perform the next action in our sequence - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - ChannelFuture channelFuture = actionHandler().apply(outboundMessage()); - - channelFuture.addListeners( - future -> actionHandler().resetFuture(), - future -> finished.setSuccess()); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - return finished; - } - - public abstract static class Builder, P extends ProbingAction> { - - public abstract B delay(Duration value); - - public abstract B outboundMessage(O value); - - public abstract B protocol(Protocol value); - - abstract P autoBuild(); - - public P build() { - P probingAction = autoBuild(); - probingAction.protocol().probingAction(probingAction); - return probingAction; - } - } - /** - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified - */ - static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } - -} - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java deleted file mode 100644 index eeecb468fce..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ /dev/null @@ -1,86 +0,0 @@ -// 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.monitoring.blackbox.handlers; - -import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.flogger.FluentLogger; - -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler.Sharable; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.SslProvider; -import java.security.cert.X509Certificate; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLParameters; - -/** - * Adds a client side SSL handler to the channel pipeline. - * - *

This must be the first handler provided for any handler provider list, if it is - * provided. The type parameter {@code C} is needed so that unit tests can construct this handler - * that works with {@link EmbeddedChannel}; - */ -@Singleton -@Sharable -public class SslClientInitializer extends ChannelInitializer { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - private final SslProvider sslProvider; - private final X509Certificate[] trustedCertificates; - - @Inject - public SslClientInitializer(SslProvider sslProvider) { - // null uses the system default trust store. - this(sslProvider, null); - } - - @VisibleForTesting - SslClientInitializer(SslProvider sslProvider, X509Certificate[] trustCertificates) { - logger.atInfo().log("Client SSL Provider: %s", sslProvider); - this.sslProvider = sslProvider; - this.trustedCertificates = trustCertificates; - } - - @Override - protected void initChannel(C channel) throws Exception { - Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - checkNotNull(protocol, "Protocol is not set for channel: %s", channel); - SslHandler sslHandler = - SslContextBuilder.forClient() - .sslProvider(sslProvider) - .trustManager(trustedCertificates) - .build() - .newHandler(channel.alloc(), protocol.host(), protocol.port()); - - // Enable hostname verification. - SSLEngine sslEngine = sslHandler.engine(); - SSLParameters sslParameters = sslEngine.getSSLParameters(); - sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); - sslEngine.setSSLParameters(sslParameters); - - channel.pipeline().addLast(sslHandler); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java deleted file mode 100644 index 1a1664a3c3c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2018 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.monitoring.blackbox.handlers; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import java.net.URL; -import javax.inject.Inject; - -public class WebWhoisActionHandler extends ActionHandler { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - @Inject - public WebWhoisActionHandler() {} - - @Override - public void channelRead0(ChannelHandlerContext ctx, HttpResponse response) throws Exception{ - if (response.status() == HttpResponseStatus.OK) { - logger.atInfo().log("Recieved Successful HttpResponseStatus"); - finished.setSuccess(); - System.out.println(response); - - } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { - - //Obtain url to be redirected to - URL url = new URL(response.headers().get("Location")); - - //From url, extract new host, port, and path - String newHost = url.getHost(); - String newPath = url.getPath(); - int newPort = url.getDefaultPort(); - - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); - - - Protocol oldProtocol = ctx.channel().attr(PROTOCOL_KEY).get(); - - //Build new Protocol from new attributes - ProbingAction currentAction = oldProtocol.probingAction(); - - //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort).toBuilder().build() - .host(newHost) - .path(newPath); - - //Modify HttpRequest sent to remote host to reflect new path and host - FullHttpRequest httpRequest = ((DefaultFullHttpRequest) currentAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); - - - //Create new probingAction that takes in the new Protocol and HttpRequest message - ProbingAction redirectedAction = currentAction., NewChannelAction>toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .build(); - - oldProtocol.probingAction(redirectedAction); - //close this channel as we no longer need it - ChannelFuture future = ctx.close(); - future.addListener( - f -> { - logger.atInfo().log("Successfully Closed Connection"); - - //Once channel is closed, establish new connection to redirected host, and repeat same actions - ChannelFuture secondFuture = redirectedAction.call(); - - //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - - } - ); - } else { - finished.setFailure(new RuntimeException()); - logger.atWarning().log(String.format("Received Response: %s", response.status())); - - } - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java deleted file mode 100644 index 01b93866b14..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/Handlers/ActionHandlerTest.java +++ /dev/null @@ -1,85 +0,0 @@ -// 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.monitoring.blackbox.Handlers; - -import static com.google.common.truth.Truth.assertThat; - -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelPromise; -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - - -/** Unit tests for {@link ActionHandler}. */ -@RunWith(JUnit4.class) -public class TestActionHandler { - - private final ActionHandler actionHandler = new ActionHandler(); - private EmbeddedChannel channel; - - @Before - public void setup() { - channel = new EmbeddedChannel(actionHandler); - } - - @Test - public void testHandler_Params() { - //initial check on Channel Activity - assertThat(channel.isActive()).isTrue(); - - - //Ensures channel Handler points to is right what - assertThat(actionHandler.getChannel()).isEqualTo(channel); - } - - @Test - public void testHandler_Behavior() { - //initial check on Channel Activity - assertThat(channel.isActive()).isTrue(); - - - ByteBuf outboundBuffer = Unpooled.copyInt(64); - - //Use ActionHandler's write method to check if the future returned is accurate - //and that it accurately writes out the inputBuffer - assertThat(actionHandler.apply(outboundBuffer)).isEqualTo(actionHandler.getFinished()); - assertThat(channel.outboundMessages().poll()).isEqualTo(outboundBuffer); - - //Creates Promise that is set to success when something changes on actionHandler's future - ChannelPromise testPromise = channel.newPromise(); - actionHandler.getFinished().addListener(f -> testPromise.setSuccess()); - - //Ensure that before reading inbound data, actionHandler's future stays inactive - assertThat(testPromise.isSuccess()).isFalse(); - - ByteBuf inputBuffer = Unpooled.copyInt(128); - - //Check that ActionHandler doesn't do anything to inbound Buffer - assertThat(channel.writeInbound(inputBuffer)).isFalse(); - - - //ensures that actionHandler's future's listener is active and that it is set to success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(actionHandler.getFinished().isSuccess()).isTrue(); - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java deleted file mode 100644 index 5d9a8b5a977..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ /dev/null @@ -1,147 +0,0 @@ -// 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.US_ASCII; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; -import io.netty.handler.codec.http.cookie.ClientCookieEncoder; -import io.netty.handler.codec.http.cookie.Cookie; -import io.netty.handler.codec.http.cookie.ServerCookieEncoder; - -/** Utility class for various helper methods used in testing. */ -public class TestUtils { - - public static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - - public static FullHttpRequest makeHttpGetRequest(String host, String path) { - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); - request.headers().set("host", host).setInt("content-length", 0); - return request; - } - - public static FullHttpResponse makeHttpResponse(String content, HttpResponseStatus status) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buf); - response.headers().setInt("content-length", buf.readableBytes()); - return response; - } - - public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status); - response.headers().setInt("content-length", 0); - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpRequest makeEppHttpRequest( - String content, - String host, - String path, - String accessToken, - String sslClientCertificateHash, - String clientAddress, - Cookie... cookies) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "application/epp+xml") - .set("accept", "application/epp+xml") - .set("X-SSL-Certificate", sslClientCertificateHash) - .set("X-Forwarded-For", clientAddress); - if (cookies.length != 0) { - request.headers().set("cookie", ClientCookieEncoder.STRICT.encode(cookies)); - } - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); - return response; - } - - public static FullHttpResponse makeEppHttpResponse( - String content, HttpResponseStatus status, Cookie... cookies) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "application/epp+xml"); - for (Cookie cookie : cookies) { - response.headers().add("set-cookie", ServerCookieEncoder.STRICT.encode(cookie)); - } - return response; - } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java deleted file mode 100644 index 399bc9c4c35..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright 2018 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.monitoring.blackbox.handlers; - -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.base.Throwables; -import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.ReferenceCountUtil; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import org.junit.rules.ExternalResource; - -/** - * Helper for setting up and testing client / server connection with netty. - * - *

Used in {@link SslClientInitializerTest} - */ -final class NettyRule extends ExternalResource { - - // All I/O operations are done inside the single thread within this event loop group, which is - // different from the main test thread. Therefore synchronizations are required to make sure that - // certain I/O activities are finished when assertions are performed. - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - - // Handler attached to server's channel to record the request received. - private EchoHandler echoHandler; - - // Handler attached to client's channel to record the response received. - private DumpHandler dumpHandler; - - private Channel channel; - - /** Sets up a server channel bound to the given local address. */ - void setUpServer(LocalAddress localAddress, ChannelHandler handler) { - checkState(echoHandler == null, "Can't call setUpServer twice"); - echoHandler = new EchoHandler(); - ChannelInitializer serverInitializer = - new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) { - // Add the given handler - ch.pipeline().addLast(handler); - // Add the "echoHandler" last to log the incoming message and send it back - ch.pipeline().addLast(echoHandler); - } - }; - ServerBootstrap sb = - new ServerBootstrap() - .group(eventLoopGroup) - .channel(LocalServerChannel.class) - .childHandler(serverInitializer); - ChannelFuture unusedFuture = sb.bind(localAddress).syncUninterruptibly(); - } - - /** Sets up a client channel connecting to the give local address. */ - void setUpClient( - LocalAddress localAddress, - Protocol protocol, - ChannelHandler handler) { - checkState(echoHandler != null, "Must call setUpServer before setUpClient"); - checkState(dumpHandler == null, "Can't call setUpClient twice"); - dumpHandler = new DumpHandler(); - ChannelInitializer clientInitializer = - new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) throws Exception { - // Add the given handler - ch.pipeline().addLast(handler); - // Add the "dumpHandler" last to log the incoming message - ch.pipeline().addLast(dumpHandler); - } - }; - Bootstrap b = - new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class) - .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol); - channel = b.connect(localAddress).syncUninterruptibly().channel(); - } - - void checkReady() { - checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); - } - - /** - * Test that a message can go through, both inbound and outbound. - * - *

The client writes the message to the server, which echos it back and saves the string in its - * promise. The client receives the echo and saves it in its promise. All these activities happens - * in the I/O thread, and this call itself returns immediately. - */ - void assertThatMessagesWork() throws Exception { - checkReady(); - assertThat(channel.isActive()).isTrue(); - - writeToChannelAndFlush(channel, "Hello, world!"); - assertThat(echoHandler.getRequestFuture().get()).isEqualTo("Hello, world!"); - assertThat(dumpHandler.getResponseFuture().get()).isEqualTo("Hello, world!"); - } - - Channel getChannel() { - checkReady(); - return channel; - } - - ThrowableSubject assertThatServerRootCause() { - checkReady(); - return assertThat( - Throwables.getRootCause( - assertThrows(ExecutionException.class, () -> echoHandler.getRequestFuture().get()))); - } - - ThrowableSubject assertThatClientRootCause() { - checkReady(); - return assertThat( - Throwables.getRootCause( - assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); - } - - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - private static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } - - /** A handler that dumps its inbound message to a promise that can be inspected later. */ - private static class DumpHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture responseFuture = new CompletableFuture<>(); - - Future getResponseFuture() { - return responseFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - // There is no more use of this message, we should release its reference count so that it - // can be more effectively garbage collected by Netty. - ReferenceCountUtil.release(msg); - // Save the string in the promise and make it as complete. - responseFuture.complete(response); - } - - /** Saves any inbound error into the failure cause of the promise. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); - } - } - - @Override - protected void after() { - Future unusedFuture = eventLoopGroup.shutdownGracefully(); - } - - private static void writeToChannelAndFlush(Channel channel, String data) { - ChannelFuture unusedFuture = - channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java deleted file mode 100644 index f7af491e39e..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/RedirectHandler.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -public class RedirectHandler { - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java deleted file mode 100644 index 6725643c48d..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ /dev/null @@ -1,205 +0,0 @@ -// 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.monitoring.blackbox.handlers; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; -import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; -import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SniHandler; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.SslProvider; -import io.netty.handler.ssl.util.SelfSignedCertificate; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.cert.CertPathBuilderException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import javax.net.ssl.SSLException; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; - -/** - * Unit tests for {@link SslClientInitializer}. - * - *

To validate that the handler accepts & rejects connections as expected, a test server and a - * test client are spun up, and both connect to the {@link LocalAddress} within the JVM. This avoids - * the overhead of routing traffic through the network layer, even if it were to go through - * loopback. It also alleviates the need to pick a free port to use. - * - *

The local addresses used in each test method must to be different, otherwise tests run in - * parallel may interfere with each other. - */ -@RunWith(Parameterized.class) -public class SslClientInitializerTest { - - /** Fake host to test if the SSL engine gets the correct peer host. */ - private static final String SSL_HOST = "www.example.tld"; - - /** Fake port to test if the SSL engine gets the correct peer port. */ - private static final int SSL_PORT = 12345; - - @Rule - public NettyRule nettyRule = new NettyRule(); - - @Parameter(0) - public SslProvider sslProvider; - - // We do our best effort to test all available SSL providers. - @Parameters(name = "{0}") - public static SslProvider[] data() { - return OpenSsl.isAvailable() - ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[] {SslProvider.JDK}; - } - - /** Saves the SNI hostname received by the server, if sent by the client. */ - private String sniHostReceived; - - /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .build() - .host(SSL_HOST); - - private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) - throws Exception { - SslContext sslContext = SslContextBuilder.forServer(privateKey, certificate).build(); - return new SniHandler( - hostname -> { - sniHostReceived = hostname; - return sslContext; - }); - } - - @Test - public void testSuccess_swappedInitializerWithSslHandler() throws Exception { - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider); - EmbeddedChannel channel = new EmbeddedChannel(); - channel.attr(PROTOCOL_KEY).set(PROTOCOL); - ChannelPipeline pipeline = channel.pipeline(); - pipeline.addLast(sslClientInitializer); - ChannelHandler firstHandler = pipeline.first(); - assertThat(firstHandler.getClass()).isEqualTo(SslHandler.class); - SslHandler sslHandler = (SslHandler) firstHandler; - assertThat(sslHandler.engine().getPeerHost()).isEqualTo(SSL_HOST); - assertThat(sslHandler.engine().getPeerPort()).isEqualTo(SSL_PORT); - assertThat(channel.isActive()).isTrue(); - } - - @Test - public void testSuccess_protocolAttributeNotSet() { - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider); - EmbeddedChannel channel = new EmbeddedChannel(); - ChannelPipeline pipeline = channel.pipeline(); - pipeline.addLast(sslClientInitializer); - // Channel initializer swallows error thrown, and closes the connection. - assertThat(channel.isActive()).isFalse(); - } - - @Test - public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Exception { - SelfSignedCertificate ssc = new SelfSignedCertificate(SSL_HOST); - LocalAddress localAddress = - new LocalAddress("DEFAULT_TRUST_MANAGER_REJECT_SELF_SIGNED_CERT_" + sslProvider); - nettyRule.setUpServer(localAddress, getServerHandler(ssc.key(), ssc.cert())); - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider); - nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); - // The connection is now terminated, both the client side and the server side should get - // exceptions. - nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); - nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); - assertThat(nettyRule.getChannel().isActive()).isFalse(); - } - - @Test - public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws Exception { - LocalAddress localAddress = - new LocalAddress("CUSTOM_TRUST_MANAGER_ACCEPT_CERT_SIGNED_BY_TRUSTED_CA_" + sslProvider); - - // Generate a new key pair. - KeyPair keyPair = getKeyPair(); - - // Generate a self signed certificate, and use it to sign the key pair. - SelfSignedCertificate ssc = new SelfSignedCertificate(); - X509Certificate cert = signKeyPair(ssc, keyPair, SSL_HOST); - - // Set up the server to use the signed cert and private key to perform handshake; - PrivateKey privateKey = keyPair.getPrivate(); - nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); - - // Set up the client to trust the self signed cert used to sign the cert that server provides. - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); - - setUpSslChannel(nettyRule.getChannel(), cert); - nettyRule.assertThatMessagesWork(); - - // Verify that the SNI extension is sent during handshake. - assertThat(sniHostReceived).isEqualTo(SSL_HOST); - } - - @Test - public void testFailure_customTrustManager_wrongHostnameInCertificate() throws Exception { - LocalAddress localAddress = - new LocalAddress("CUSTOM_TRUST_MANAGER_WRONG_HOSTNAME_" + sslProvider); - - // Generate a new key pair. - KeyPair keyPair = getKeyPair(); - - // Generate a self signed certificate, and use it to sign the key pair. - SelfSignedCertificate ssc = new SelfSignedCertificate(); - X509Certificate cert = signKeyPair(ssc, keyPair, "wrong.com"); - - // Set up the server to use the signed cert and private key to perform handshake; - PrivateKey privateKey = keyPair.getPrivate(); - nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); - - // Set up the client to trust the self signed cert used to sign the cert that server provides. - SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, sslClientInitializer); - - // When the client rejects the server cert due to wrong hostname, both the client and server - // should throw exceptions. - nettyRule.assertThatClientRootCause().isInstanceOf(CertificateException.class); - nettyRule.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST); - nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); - assertThat(nettyRule.getChannel().isActive()).isFalse(); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java deleted file mode 100644 index 7b4aae50106..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java +++ /dev/null @@ -1,94 +0,0 @@ -// 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.monitoring.blackbox.handlers; - -import static com.google.common.truth.Truth.assertThat; - -import io.netty.channel.Channel; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.ssl.util.SelfSignedCertificate; -import java.math.BigInteger; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.SecureRandom; -import java.security.Security; -import java.security.cert.X509Certificate; -import java.time.Duration; -import java.time.Instant; -import java.util.Date; -import javax.net.ssl.SSLSession; -import javax.security.auth.x500.X500Principal; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.x509.X509V3CertificateGenerator; - -/** - * Utility class that provides methods used by {@link SslClientInitializerTest} - */ -public class SslInitializerTestUtils { - - static { - Security.addProvider(new BouncyCastleProvider()); - } - - public static KeyPair getKeyPair() throws Exception { - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); - keyPairGenerator.initialize(2048, new SecureRandom()); - return keyPairGenerator.generateKeyPair(); - } - - /** - * Signs the given key pair with the given self signed certificate. - * - * @return signed public key (of the key pair) certificate - */ - public static X509Certificate signKeyPair( - SelfSignedCertificate ssc, KeyPair keyPair, String hostname) throws Exception { - X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); - X500Principal dnName = new X500Principal("CN=" + hostname); - certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); - certGen.setSubjectDN(dnName); - certGen.setIssuerDN(ssc.cert().getSubjectX500Principal()); - certGen.setNotBefore(Date.from(Instant.now().minus(Duration.ofDays(1)))); - certGen.setNotAfter(Date.from(Instant.now().plus(Duration.ofDays(1)))); - certGen.setPublicKey(keyPair.getPublic()); - certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); - return certGen.generate(ssc.key(), "BC"); - } - - /** - * Verifies tha the SSL channel is established as expected, and also sends a message to the server - * and verifies if it is echoed back correctly. - * - * @param certs The certificate that the server should provide. - * @return The SSL session in current channel, can be used for further validation. - */ - static SSLSession setUpSslChannel( - Channel channel, - X509Certificate... certs) - throws Exception { - SslHandler sslHandler = channel.pipeline().get(SslHandler.class); - // Wait till the handshake is complete. - sslHandler.handshakeFuture().get(); - - assertThat(channel.isActive()).isTrue(); - assertThat(sslHandler.handshakeFuture().isSuccess()).isTrue(); - assertThat(sslHandler.engine().getSession().isValid()).isTrue(); - assertThat(sslHandler.engine().getSession().getPeerCertificates()) - .asList() - .containsExactlyElementsIn(certs); - // Returns the SSL session for further assertion. - return sslHandler.engine().getSession(); - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java deleted file mode 100644 index 001c935d70a..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ /dev/null @@ -1,208 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; - - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; -import google.registry.monitoring.blackbox.Protocol; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelPromise; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import org.joda.time.Duration; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ -@RunWith(JUnit4.class) -public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; - private static final int HTTPS_PORT = 443; - private static final String HTTP_REDIRECT = "http://"; - private static final String HTTPS_REDIRECT = "https://"; - private static final String REDIRECT_HOST = "www.example.com"; - private static final String REDIRECT_PATH = "/test/path"; - private static final String TARGET_HOST = "whois.nic.tld"; - private static final Duration DEFAULT_DURATION = new Duration(0L); - - - private EmbeddedChannel channel; - private ActionHandler actionHandler; - - /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { - return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); - } - - /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); - } - - /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); - } - - /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .build(); - } - - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); - } - - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - - @Test - public void testSuccess_responseOk() { - //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); - - //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); - - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that we successfully receivved good response and protocol is unchanged - assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); - } - - @Test - public void testSuccess_responseBad() { - //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); - - //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - - //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); - } - - @Test - public void testSuccess_redirectCloseChannel() { - //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); - - //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); - - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - - - channel.writeInbound(response); - - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - - - } - - @Test - public void testSuccess_redirectHost() { - //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - - //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - - - channel.writeInbound(originalResponse); - - //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - - - } - -} From 715184c942e1dd4b10b67c19907a02b4b5297550 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 10 Jul 2019 17:34:38 -0400 Subject: [PATCH 155/337] Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle --- .../monitoring/blackbox/package-info.java | 15 --------------- .../monitoring/blackbox/package-info.java | 15 --------------- settings.gradle | 5 ++--- 3 files changed, 2 insertions(+), 33 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/package-info.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/package-info.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java deleted file mode 100644 index 21c8764701c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java +++ /dev/null @@ -1,15 +0,0 @@ -// 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.monitoring.blackbox; \ No newline at end of file diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java deleted file mode 100644 index 21c8764701c..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/package-info.java +++ /dev/null @@ -1,15 +0,0 @@ -// 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.monitoring.blackbox; \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 0cd8f4dd707..eea358cfc0e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -30,11 +30,10 @@ rootProject.name = 'nomulus' include 'core' include 'prober' include 'proxy' -include 'third_party' -include 'util' include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' -include 'prober' +include 'third_party' +include 'util' From 6aeb55ecdb20477e6166b750fc0c244737264144 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 10 Jul 2019 17:41:55 -0400 Subject: [PATCH 156/337] Fully Updated ActionHandler (missing updated JavaDoc) --- .../blackbox/handlers/ActionHandler.java | 58 +++++++------------ 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index a4df56408b5..c502f94015f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -15,72 +15,58 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import com.google.common.flogger.StackSize; -import io.netty.channel.ChannelInboundHandlerAdapter; +import google.registry.monitoring.blackbox.messages.InboundMarker; +import google.registry.monitoring.blackbox.messages.OutboundMarker; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpResponse; -import java.util.function.Function; -import javax.inject.Inject; /** * - * @param Generic Type of Inbound Message - * @param Generic Type of Outbound Message + * * Abstract class that tells sends message down pipeline and * and tells listeners to move on when the message is received. */ -public abstract class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); protected ChannelPromise finished; - private Channel channel; - + protected OutboundMarker outboundMessage; - /** returns ChannelPromise for when inbound message is recieved - * a - * @param outboundMessage - * @return - */ - @Override - public ChannelFuture apply(O outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline + /** Writes and flushes specified outboundMessage to channel pipeline and returns future + * that is marked as success when ActionHandler next reads from the channel */ + public ChannelFuture getFuture(OutboundMarker outboundMessage) { + //Action Handlers subclasses require the outboundMessage for additional logic + this.outboundMessage = outboundMessage; - channel.writeAndFlush(outboundMessage); + //returns the ChannelPromise initialized return finished; - - } - - public void resetFuture() { - finished = channel.newPromise(); } @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler - - channel = ctx.channel(); finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ - //Only purpose of Handler is to mark future as a success - + public void channelRead0(ChannelHandlerContext ctx, InboundMarker inboundMessage) throws Exception { + //simply marks finished as success finished.setSuccess(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); + logger.atSevere().withCause(cause).log(String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), + ctx.channel().pipeline().toString())); + + finished.setFailure(cause); + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } From 3f20384b596f12624c65690754b04902e9b88d08 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 10 Jul 2019 17:54:18 -0400 Subject: [PATCH 157/337] Added changed Protocol and both Inbound and Outbound Markers --- .../monitoring/blackbox/Protocol.java | 65 +++++-------------- .../blackbox/messages/InboundMarker.java | 22 +++++++ .../blackbox/messages/OutboundMarker.java | 21 ++++++ 3 files changed, 58 insertions(+), 50 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 913b7d7627e..8e39866cd56 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -16,6 +16,7 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; import javax.inject.Provider; @@ -29,7 +30,7 @@ public abstract class Protocol { public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); /** * Default names associated with each protocol */ @@ -38,77 +39,41 @@ public abstract class Protocol { final static String WHOIS_PROTOCOL_NAME = "WHOIS"; final static String RDAP_PROTOCOL_NAME = "RDAP"; - private String host; - private String path = ""; - private ProbingAction probingAction; - - /** Setter method for Protocol's host*/ - public Protocol host(String host) { - this.host = host; - return this; - } - - /** Getter method for Protocol's host*/ - public String host() { - return host; - } - - /** Setter method for Protocol's path*/ - public Protocol path(String path) { - this.path = path; - return this; - } - - /** Getter method for Protocol's path*/ - public String path() { - return path; - } - - /** Setter method for Protocol's ProbingAction parent*/ - public Protocol probingAction(ProbingAction probingAction) { - this.probingAction = probingAction; - return this; - } - - /** Getter method for Protocol's path*/ - public ProbingAction probingAction() { - return probingAction; - } - - /** If connection associated with Protocol is persistent, which is only EPP */ - public boolean persistentConnection() { - return name() == EPP_PROTOCOL_NAME; - } + /** Local Address of Protocol. ONLY FOR TESTING*/ + public abstract LocalAddress address(); /** Protocol Name */ - public abstract String name(); + abstract String name(); /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - public abstract ImmutableList> handlerProviders(); + abstract ImmutableList> handlerProviders(); + /** If connection associated with Protocol is persistent, which is only EPP */ + abstract boolean persistentConnection(); public abstract Builder toBuilder(); public static Builder builder() { - return new AutoValue_Protocol.Builder(); + return new AutoValue_Protocol.Builder().address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder { + public abstract Builder address(LocalAddress value); + public abstract Builder name(String value); public abstract Builder port(int num); public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder persistentConnection(boolean value); + public abstract Protocol build(); } - - - } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java new file mode 100644 index 00000000000..0a16344eb65 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java @@ -0,0 +1,22 @@ +// Copyright 2019 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.monitoring.blackbox.messages; + +/** + * Simple Interface that is implemented by all classes that serve + * as inboundMessages in the channel pipelines + */ +public interface InboundMarker {} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java new file mode 100644 index 00000000000..413a97ea0a0 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java @@ -0,0 +1,21 @@ +// Copyright 2019 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.monitoring.blackbox.messages; + +/** + * Simple Interface that is implemented by all classes that serve + * as outboundMessages in the channel pipelines + */ +public interface OutboundMarker {} From bcfdb05b559e7ec1a783b9749d5f8d6c780111b7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 09:25:54 -0400 Subject: [PATCH 158/337] Removed AutoVaue ignore clause from .gitignore --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 199c4fe3979..327b22fe2e7 100644 --- a/.gitignore +++ b/.gitignore @@ -85,9 +85,6 @@ nomulus.iws # Javascript output **/out/* -# AutoValue generated code -AutoValue_.*.java - ###################################################################### # Python Ignores From d1fdc03e4b48fce6fb2697b9a589e1522a3163fc Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:23:33 -0400 Subject: [PATCH 159/337] removed unneccessary dependencies in build.gradle --- prober/build.gradle | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index e826fb6c37a..0f7931519b3 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,15 +1,25 @@ +// Copyright 2019 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. + apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] - compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] compile deps['io.netty:netty-buffer'] @@ -18,26 +28,16 @@ dependencies { compile deps['io.netty:netty-common'] compile deps['io.netty:netty-handler'] compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - //compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor annotationProcessor deps['com.google.auto.value:auto-value'] testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] -} \ No newline at end of file +} + From b4b64e3421cbecc2ff7d7fcfaffb86b904e564d0 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:47:39 -0400 Subject: [PATCH 160/337] Fixed Javadoc and comments for ActionHandler --- .../blackbox/handlers/ActionHandler.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index c502f94015f..814efd01e33 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -23,10 +23,16 @@ import io.netty.channel.ChannelPromise; /** + *Superclass of all Handlers placed at end of channel pipeline * + *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler}, as it should only be passed in + * messages that implement the {@link InboundMarker} interface.

* - * Abstract class that tells sends message down pipeline and - * and tells listeners to move on when the message is received. + *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMarker} + * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception + * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses + * specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -35,16 +41,16 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); } } - From 55306841c65b8a0ccf699fbbd641b0a1dcb6d546 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:55:18 -0400 Subject: [PATCH 161/337] Fixed comments and JavaDoc on other files --- prober/build.gradle | 7 +++++++ .../monitoring/blackbox/Protocol.java | 19 +++---------------- .../blackbox/messages/InboundMarker.java | 3 +-- .../blackbox/messages/OutboundMarker.java | 3 +-- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 0f7931519b3..4590fe28148 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -20,6 +20,7 @@ dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] compile deps['io.netty:netty-buffer'] @@ -28,16 +29,22 @@ dependencies { compile deps['io.netty:netty-common'] compile deps['io.netty:netty-handler'] compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') // Include auto-value in compile until nebula-lint understands // annotationProcessor annotationProcessor deps['com.google.auto.value:auto-value'] testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 8e39866cd56..080acc30584 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -17,41 +17,29 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import io.netty.channel.local.LocalAddress; -import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; import javax.inject.Provider; /** - * Protocol Class packages all static variables necessary for a certain type of connection - * Both the host and the path can be changed for the same protocol - * Mainly packages the handlers necessary for the requisite channel pipeline + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection */ @AutoValue public abstract class Protocol { - public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** - * Default names associated with each protocol - */ - final static String EPP_PROTOCOL_NAME = "EPP"; - final static String DNS_PROTOCOL_NAME = "DNS"; - final static String WHOIS_PROTOCOL_NAME = "WHOIS"; - final static String RDAP_PROTOCOL_NAME = "RDAP"; /** Local Address of Protocol. ONLY FOR TESTING*/ public abstract LocalAddress address(); - /** Protocol Name */ abstract String name(); - /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ abstract ImmutableList> handlerProviders(); - /** If connection associated with Protocol is persistent, which is only EPP */ + /** Boolean that notes if connection associated with Protocol is persistent.*/ abstract boolean persistentConnection(); public abstract Builder toBuilder(); @@ -76,4 +64,3 @@ public static abstract class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java index 0a16344eb65..edd541f98f7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java @@ -15,8 +15,7 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve - * as inboundMessages in the channel pipelines + * Simple Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ public interface InboundMarker {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java index 413a97ea0a0..eb2c14e8096 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java @@ -15,7 +15,6 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve - * as outboundMessages in the channel pipelines + * Simple Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMarker {} From d8bbdc56b8cbc1f35ef9addf4a46142045fa6963 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 10:57:07 -0400 Subject: [PATCH 162/337] EOL added --- .../main/java/google/registry/monitoring/blackbox/Protocol.java | 1 + .../registry/monitoring/blackbox/handlers/ActionHandler.java | 1 + .../registry/monitoring/blackbox/messages/OutboundMarker.java | 1 + 3 files changed, 3 insertions(+) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 080acc30584..fa9f3814ddc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -64,3 +64,4 @@ public static abstract class Builder { public abstract Protocol build(); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 814efd01e33..c26882e5f4c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -76,3 +76,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java index eb2c14e8096..bd80aa0a062 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java @@ -18,3 +18,4 @@ * Simple Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMarker {} + From 5bda3381b3e4c02a6740821ad6919a2ecda4d2be Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 12 Jul 2019 12:10:20 -0400 Subject: [PATCH 163/337] Removed Unnecessary Files --- .../google/registry/monitoring/blackbox/ActionHandler.java | 5 ----- .../google/registry/monitoring/blackbox/ProbingAction.java | 5 ----- .../google/registry/monitoring/blackbox/ProbingSequence.java | 5 ----- .../google/registry/monitoring/blackbox/ProbingStep.java | 5 ----- .../java/google/registry/monitoring/blackbox/Protocol.java | 5 ----- .../java/google/registry/monitoring/blackbox/TestToken.java | 5 ----- .../main/java/google/registry/monitoring/blackbox/Token.java | 5 ----- 7 files changed, 35 deletions(-) delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java deleted file mode 100644 index a4d36657721..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ActionHandler { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java deleted file mode 100644 index 6b26913d425..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingAction { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java deleted file mode 100644 index 9f3617135a4..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingSequence { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java deleted file mode 100644 index b8b237a1e91..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingStep { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java deleted file mode 100644 index 75d13b3039a..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Protocol { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java deleted file mode 100644 index 98f21f8d63a..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class TestToken { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java deleted file mode 100644 index 16f05be0430..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Token { - -} From 3b587abeb08d6a50d3fdcea70c3c6aee7987422f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 12 Jul 2019 13:32:44 -0400 Subject: [PATCH 164/337] fixed .gradle files styles --- settings.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.gradle b/settings.gradle index eea358cfc0e..10ae29b66d1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -30,10 +30,10 @@ rootProject.name = 'nomulus' include 'core' include 'prober' include 'proxy' +include 'third_party' +include 'util' include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' -include 'third_party' -include 'util' From c950efe5faacfe09a13247c7e34ba8920106ae74 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 15:15:52 -0400 Subject: [PATCH 165/337] Removed outbound message from ActionHandler's fields and renamed Marker Interfaces --- .../blackbox/handlers/ActionHandler.java | 9 ++------ .../blackbox/messages/InboundMarker.java | 21 ------------------- .../blackbox/messages/InboundMessageType.java | 5 ++--- .../blackbox/messages/OutboundMarker.java | 21 ------------------- .../messages/OutboundMessageType.java | 19 ++--------------- 5 files changed, 6 insertions(+), 69 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMarker.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMarker.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index c26882e5f4c..22df091833d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -23,7 +23,7 @@ import io.netty.channel.ChannelPromise; /** - *Superclass of all Handlers placed at end of channel pipeline + *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler}, as it should only be passed in * messages that implement the {@link InboundMarker} interface.

@@ -39,14 +39,9 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler Date: Mon, 15 Jul 2019 15:17:40 -0400 Subject: [PATCH 166/337] Fixed javadoc for Marker Interfaced --- .../monitoring/blackbox/messages/InboundMessageType.java | 2 +- .../monitoring/blackbox/messages/OutboundMessageType.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 7f4b4135516..0c1260becf2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ public interface InboundMessageType {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index e1ed12f56d9..0dd17e9d4a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.messages; /** - * Simple Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType {} From 1ed07fd21da48774114cafe86a80f675abf9e179 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 15:18:51 -0400 Subject: [PATCH 167/337] Modified Comments on ActionHandler --- .../blackbox/handlers/ActionHandler.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 22df091833d..dfd88cba1ce 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,8 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.messages.InboundMarker; -import google.registry.monitoring.blackbox.messages.OutboundMarker; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -25,22 +25,22 @@ /** *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler}, as it should only be passed in - * messages that implement the {@link InboundMarker} interface.

+ *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMarker} + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses * specify further work to be done for specific kinds of channel pipelines.

*/ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); protected ChannelPromise finished; - /** Takes in {@link OutboundMarker} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ public ChannelFuture getFuture() { return finished; } @@ -53,7 +53,7 @@ public void handlerAdded(ChannelHandlerContext ctx) { } @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMarker inboundMessage) throws Exception { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws Exception { //simply marks finished as success finished.setSuccess(); } From fd5e56db3a9017cad59d54e199bb058ea7ddd898 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 15:40:37 -0400 Subject: [PATCH 168/337] Removed LocalAddress from Protocol --- .../google/registry/monitoring/blackbox/Protocol.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index fa9f3814ddc..b0071ea4467 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,7 +16,6 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.local.LocalAddress; import io.netty.channel.ChannelHandler; import javax.inject.Provider; @@ -26,12 +25,6 @@ @AutoValue public abstract class Protocol { - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - - /** Local Address of Protocol. ONLY FOR TESTING*/ - public abstract LocalAddress address(); - abstract String name(); public abstract int port(); @@ -45,14 +38,12 @@ public abstract class Protocol { public abstract Builder toBuilder(); public static Builder builder() { - return new AutoValue_Protocol.Builder().address(DEFAULT_ADDRESS); + return new AutoValue_Protocol.Builder(); } @AutoValue.Builder public static abstract class Builder { - public abstract Builder address(LocalAddress value); - public abstract Builder name(String value); public abstract Builder port(int num); From 3c361ec01f7e585b9fb245017837dd983184c687 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 15 Jul 2019 16:13:43 -0400 Subject: [PATCH 169/337] Fixed Travis Build Issues --- prober/build.gradle | 5 ++--- settings.gradle | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 4590fe28148..e287bfd1bb9 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -18,7 +18,7 @@ createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober dependencies { def deps = rootProject.dependencyMap - + compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] @@ -34,7 +34,7 @@ dependencies { runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - + testCompile deps['com.google.truth:truth'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] @@ -47,4 +47,3 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } - diff --git a/settings.gradle b/settings.gradle index 10ae29b66d1..9b2d11de8da 100644 --- a/settings.gradle +++ b/settings.gradle @@ -36,4 +36,3 @@ include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' - From fe03464864168e2a4dcec1c4ca4768d38af28a75 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 170/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 3 +- .../google/registry/xjc/package-info.java | 3 +- prober/build.gradle | 33 ++-- .../monitoring/blackbox/NewChannelAction.java | 136 +++++++++++++ .../registry/monitoring/blackbox/Prober.java | 23 +-- .../monitoring/blackbox/ProbingAction.java | 186 ++++++++++++++++++ .../handlers/ServerSideException.java | 15 ++ .../handlers/SslClientInitializer.java | 117 +++++++++++ .../handlers/WebWhoisActionHandler.java | 137 +++++++++++++ .../blackbox/messages/HttpRequestMessage.java | 71 ++----- .../messages/HttpResponseMessage.java | 46 +++-- .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 15 files changed, 653 insertions(+), 125 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index ddff37c6807..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,3 +14,4 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.ui; + diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 5b5456585cc..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,3 +14,4 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.xjc; + diff --git a/prober/build.gradle b/prober/build.gradle index e287bfd1bb9..a277fb4f9f3 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -4,7 +4,7 @@ // 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 +// 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, @@ -12,12 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -apply plugin: 'java' - createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') dependencies { - def deps = rootProject.dependencyMap + def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.dagger:dagger'] @@ -30,20 +28,21 @@ dependencies { compile deps['io.netty:netty-handler'] compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] - runtime deps['com.google.flogger:flogger-system-backend'] - runtime deps['com.google.auto.value:auto-value'] - runtime deps['io.netty:netty-tcnative-boringssl-static'] + runtime deps['com.google.flogger:flogger-system-backend'] + runtime deps['com.google.auto.value:auto-value'] + runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') - // Include auto-value in compile until nebula-lint understands - // annotationProcessor - annotationProcessor deps['com.google.auto.value:auto-value'] - testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] + // Include auto-value in compile until nebula-lint understands + // annotationProcessor + annotationProcessor deps['com.google.auto.value:auto-value'] + testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..0ba3a0c22be --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 433d7361d5b..333330207f1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,30 +14,17 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by - * Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** - * Main Dagger Component - */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() - .build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java new file mode 100644 index 00000000000..2441debb12d --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -0,0 +1,186 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.flogger.StackSize.SMALL; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.util.AttributeKey; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; +import java.util.concurrent.Callable; +import javax.inject.Provider; + +/** + *Superclass that represents action generated by {@link ProbingStep} + * + *

Inherits from {@link Callable}, as it has can be called + * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the + * task has been completed

+ * + *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. + * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} + * gives the outline and {@link ProbingAction} gives the details of that connection.

+ * + *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ */ + + +public abstract class ProbingAction implements Callable { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; + + + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; + } + + /** {@link Timer} that rate limits probing */ + private static final Timer timer = new HashedWheelTimer(); + + + /** Actual {@link Duration} of this delay */ + public abstract Duration delay(); + + /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ + public abstract OutboundMessageType outboundMessage(); + + /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + public abstract Channel channel(); + + /** The {@link Protocol} instance that specifies type of connection */ + public abstract Protocol protocol(); + + public abstract String host(); + + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> finished.setSuccess(), + future -> { + if (!protocol().persistentConnection()) { + + //If we created a new channel for this action, close the connection to the channel + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** + * The method that sends the {@code outboundMessage} down the channel pipeline + * + * @return future that denotes when the action has been successfully performed + */ + + @Override + public ChannelFuture call() { + + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + } + + //ChannelPromise that we use to inform ProbingStep when we are finished. + ChannelPromise finished = channel().newPromise(); + + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } + + return finished; + } + + public abstract static class Builder, P extends ProbingAction> { + + public abstract B delay(Duration value); + + public abstract B outboundMessage(OutboundMessageType value); + + public abstract B protocol(Protocol value); + + public abstract B host(String value); + + public abstract B path(String value); + + public abstract P build(); + + } + + /** + * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified + * + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified + */ + static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); + } + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java new file mode 100644 index 00000000000..ac844ac99df --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -0,0 +1,117 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.base.Preconditions.checkNotNull; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.flogger.FluentLogger; + +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslProvider; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.function.Supplier; +import javax.inject.Singleton; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; + +/** + * Adds a client side SSL handler to the channel pipeline. + * + *

Code is close to unchanged from {@link SslClientInitializer}

in proxy, but is modified + * for revised overall structure of connections, and to accomdate EPP connections

+ * + *

This must be the first handler provided for any handler provider list, if it is + * provided. The type parameter {@code C} is needed so that unit tests can construct this handler + * that works with {@link EmbeddedChannel}; + */ +@Singleton +@Sharable +public class SslClientInitializer extends ChannelInitializer { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + private final SslProvider sslProvider; + private final X509Certificate[] trustedCertificates; + private final Supplier privateKeySupplier; + private final Supplier certificateSupplier; + + + public SslClientInitializer(SslProvider sslProvider) { + // null uses the system default trust store. + //Used for WebWhois, so we don't care about privateKey and certificates, setting them to null + this(sslProvider, null, null, null); + } + + public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, Supplier certificateSupplier) { + //We use the default trust store here as well, setting trustCertificates to null + this(sslProvider, null, privateKeySupplier, certificateSupplier); + } + + @VisibleForTesting + SslClientInitializer(SslProvider sslProvider, X509Certificate[] trustCertificates) { + this(sslProvider, trustCertificates, null, null); + } + + private SslClientInitializer( + SslProvider sslProvider, + X509Certificate[] trustCertificates, + Supplier privateKeySupplier, + Supplier certificateSupplier) { + logger.atInfo().log("Client SSL Provider: %s", sslProvider); + + this.sslProvider = sslProvider; + this.trustedCertificates = trustCertificates; + this.privateKeySupplier = privateKeySupplier; + this.certificateSupplier = certificateSupplier; + } + + @Override + protected void initChannel(C channel) throws Exception { + ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); + Protocol protocol = action.protocol(); + + //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate + checkNotNull(protocol, "Protocol is not set for channel: %s", channel); + SslContextBuilder sslContextBuilder = + SslContextBuilder.forClient() + .sslProvider(sslProvider) + .trustManager(trustedCertificates); + if (privateKeySupplier != null && certificateSupplier != null) + sslContextBuilder = sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get()); + + SslHandler sslHandler = sslContextBuilder + .build() + .newHandler(channel.alloc(), action.host(), protocol.port()); + + // Enable hostname verification. + SSLEngine sslEngine = sslHandler.engine(); + SSLParameters sslParameters = sslEngine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + sslEngine.setSSLParameters(sslParameters); + + channel.pipeline().addLast(sslHandler); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java new file mode 100644 index 00000000000..21010f0e887 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -0,0 +1,137 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; + +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; +import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpResponseStatus; +import java.net.MalformedURLException; +import java.net.URL; +import javax.inject.Inject; +import org.joda.time.Duration; + +/** + *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + * + *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection + * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

+ */ +public class WebWhoisActionHandler extends ActionHandler { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + @Inject + public WebWhoisActionHandler() {} + + + /** + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + */ + @Override + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) + throws ServerSideException { + + HttpResponseMessage response = (HttpResponseMessage) msg; + + + if (response.status() == HttpResponseStatus.OK) { + logger.atInfo().log("Received Successful HttpResponseStatus"); + + finished.setSuccess(); + + logger.atInfo().log("Response Received: " + response); + + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { + + //Obtain url to be redirected to + URL url; + try { + url = new URL(response.headers().get("Location")); + } catch (MalformedURLException e) { + //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it + throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + } + //From url, extract new host, port, and path + String newHost = url.getHost(); + String newPath = url.getPath(); + int newPort = url.getDefaultPort(); + + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); + + //Construct new Protocol to reflect redirected host, path, and port + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); + + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + + //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) + .build(); + + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + + //close this channel as we no longer need it + ChannelFuture future = ctx.close(); + future.addListener( + f -> { + logger.atInfo().log("Successfully Closed Connection"); + + //Once channel is closed, establish new connection to redirected host, and repeat same actions + ChannelFuture secondFuture = redirectedAction.call(); + + //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + secondFuture.addListener(f2 -> finished.setSuccess()); + + } + ); + } else { + //Add in metrics Handling that informs MetricsCollector the response was a FAILURE + finished.setSuccess(); + logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + + } + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 92e43501438..3fb8c187ad9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -19,31 +5,19 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import java.util.Arrays; -import javax.inject.Inject; -/** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. - * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a {@code - * name} method, which returns a standard name and the current hostname.

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, - ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + @Override @@ -52,38 +26,15 @@ public HttpRequestMessage setUri(String path) { return this; } - /** - * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} - */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } - - /** - * Modifies headers to reflect new host and new path if applicable. - */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) { - setUri(args[1]); - } - - return this; + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + ByteBuf buf = request.content(); + if (buf == null) { + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - throw new IllegalArgumentException( - String.format( - "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + Arrays.toString(args), args.length)); + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - } - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 7d2ff722076..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,21 +6,33 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} - */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { + super(version, status); + } + + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } - /** - * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} - */ - public HttpResponseMessage(FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); + + return finalResponse; } + + + } diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From d20e48eecde15ed59f338d3d9e5425018c85a753 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:58:52 -0400 Subject: [PATCH 171/337] Fixed changes suggested by CydeWeys --- .../google/registry/cron/package-info.java | 2 +- .../google/registry/xml/package-info.java | 2 +- prober/build.gradle | 28 +-- .../handlers/WebWhoisActionHandlerTest.java | 221 ++++++++++++++++++ 4 files changed, 238 insertions(+), 15 deletions(-) create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java diff --git a/core/src/main/java/google/registry/cron/package-info.java b/core/src/main/java/google/registry/cron/package-info.java index 459f2513f93..49b18ca2885 100644 --- a/core/src/main/java/google/registry/cron/package-info.java +++ b/core/src/main/java/google/registry/cron/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/core/src/main/java/google/registry/xml/package-info.java b/core/src/main/java/google/registry/xml/package-info.java index f8e42585ecc..b3f27868b91 100644 --- a/core/src/main/java/google/registry/xml/package-info.java +++ b/core/src/main/java/google/registry/xml/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/prober/build.gradle b/prober/build.gradle index a277fb4f9f3..dbb7252a462 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -4,7 +4,7 @@ // 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 +// 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, @@ -12,23 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +apply plugin: 'java' + createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') dependencies { def deps = rootProject.dependencyMap - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java new file mode 100644 index 00000000000..63bb2cf5b53 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -0,0 +1,221 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.Protocol; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelPromise; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ +@RunWith(JUnit4.class) +public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; + private static final int HTTPS_PORT = 443; + private static final String HTTP_REDIRECT = "http://"; + private static final String HTTPS_REDIRECT = "https://"; + private static final String REDIRECT_HOST = "www.example.com"; + private static final String REDIRECT_PATH = "/test/path"; + private static final String TARGET_HOST = "whois.nic.tld"; + private static final Duration DEFAULT_DURATION = new Duration(0L); + + + private EmbeddedChannel channel; + private ActionHandler actionHandler; + + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { + return Protocol.builder() + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); + } + + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); + } + + /** Sets up testing channel with requisite attributes */ + private void setupChannel(Protocol protocol) { + setupActionHandler(); + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); + } + + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); + } + + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); + } + + + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; + } + + + @Test + public void testSuccess_responseOk() { + //setup + Protocol initialProtocol = createProtocol("responseOk", 0, ""); + setupChannel(initialProtocol); + + //stores future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that we successfully receivved good response and protocol is unchanged + assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + } + + @Test + public void testSuccess_responseBad() { + //setup + Protocol initialProtocol = createProtocol("responseBad", 0, ""); + setupChannel(initialProtocol); + + //stores future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, but event is not success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + + //ensures Protocol is the same + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + } + + @Test + public void testSuccess_redirectCloseChannel() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); + + //stores future + ChannelFuture future = actionHandler.apply(outboundMessage); + + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + + + } + + @Test + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + + + channel.writeInbound(originalResponse); + + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); + + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + + + } + +} From d219267ff10c2586eaa8f2874457e40a7b3b3993 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 172/337] Added missing license headers and JavaDoc --- .../handlers/ServerSideException.java | 16 ++++++- .../blackbox/messages/HttpRequestMessage.java | 45 ++++++++++++++----- .../messages/HttpResponseMessage.java | 32 ++++++++++--- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java index 5d3addb920e..441062a9e7b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; /** @@ -12,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 3fb8c187ad9..8fbb55c6339 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,13 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} + * (but needs to implement {@link OutboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion + * from {@link FullHttpRequest} to its type

+ */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +35,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,15 +42,22 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - if (buf == null) { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //creates message based on content found in original request + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //stores headers from request in finalRequest + request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); + + return finalRequest; + + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..776e7de0824 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,11 +1,33 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} + * (but needs to implement {@link InboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion + * from {@link FullHttpResponse} to its type

+ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -17,22 +39,20 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } + /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); + //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + //stores headers from response in finalResponse + response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); return finalResponse; } - - - } From 76ba85c57bea13d7fc549900128f2617412d8c15 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 173/337] Minor fix in NewChannelAction JavaDoc --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..1e7578d5679 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; - import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -28,8 +27,7 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) */ @AutoValue public abstract class NewChannelAction extends ProbingAction { From cebfab294530a7468fb323a89b80090721de4a67 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 13:33:23 -0400 Subject: [PATCH 174/337] Minor Style Fix --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 ---- .../java/google/registry/monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/handlers/WebWhoisActionHandler.java | 2 -- 3 files changed, 7 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..84cf75492f2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -52,7 +52,6 @@ public Channel channel() { return this.channel; } - @Override public abstract Builder toBuilder(); @@ -120,7 +119,6 @@ public static NewChannelAction.Builder builder() return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -129,6 +127,4 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index b0071ea4467..2a4a8d0ed76 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -55,4 +55,3 @@ public static abstract class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 21010f0e887..5b77461cd8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -131,7 +131,5 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } } - - } From d6237150fafbc2b3dba37902f67d4a95dd65efa7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 175/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 40 +-- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 17 +- .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProberModule.java | 97 ++++--- .../monitoring/blackbox/ProbingAction.java | 17 +- .../monitoring/blackbox/ProbingSequence.java | 122 +++++++++ .../monitoring/blackbox/ProbingStep.java | 170 ++++++++++++ .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 12 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 ++++ .../monitoring/blackbox/WebWhoisModule.java | 216 ++++++--------- .../exceptions/EppClientException.java | 29 ++ .../exceptions/InternalException.java | 29 ++ .../exceptions/ResponseException.java | 29 ++ .../ServerSideException.java | 4 +- .../blackbox/handlers/ActionHandler.java | 71 +++-- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/WebWhoisActionHandler.java | 19 +- .../handlers/WebWhoisMessageHandler.java | 42 +-- .../blackbox/messages/HttpRequestMessage.java | 50 +--- .../messages/HttpResponseMessage.java | 32 +-- .../blackbox/ProbingActionTest.java | 173 ++++++------ .../blackbox/ProbingSequenceStepTest.java | 219 +++++++++++++++ .../blackbox/TestServers/TestServer.java | 85 ++++++ .../blackbox/TestServers/WebWhoisServer.java | 92 +++++++ .../monitoring/blackbox/TestUtils.java | 252 ++++++++++++++++++ .../monitoring/blackbox/TokenTest.java | 60 +++++ .../blackbox/handlers/ConversionHandler.java | 23 +- .../blackbox/handlers/NettyRule.java | 201 ++++++++++++++ .../handlers/SslClientInitializerTest.java | 233 ++++++++++++++++ .../handlers/SslInitializerTestUtils.java | 95 +++++++ .../blackbox/handlers/TestActionHandler.java | 19 +- .../handlers/WebWhoisActionHandlerTest.java | 222 ++++++++++----- 36 files changed, 2433 insertions(+), 498 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java diff --git a/prober/build.gradle b/prober/build.gradle index dbb7252a462..993da44655d 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,30 +16,36 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') + //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -48,3 +54,5 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 84cf75492f2..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -52,6 +53,7 @@ public Channel channel() { return this.channel; } + @Override public abstract Builder toBuilder(); @@ -83,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -116,9 +118,10 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } + @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -127,4 +130,6 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } + } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 333330207f1..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,16 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index df8b5fdbabd..73bd9127852 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,84 +14,99 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import io.netty.channel.Channel; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SslProvider; import java.util.Set; import javax.inject.Singleton; -import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and - * stores {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link - * ProbingSequence}. + * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} + * + *

Provides

*/ @Module public class ProberModule { + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; - /** - * Default {@link Duration} chosen to be time between each {@link ProbingAction} call. - */ - private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - - /** - * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. - */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** - * {@link Provides} one global {@link Channel} class that is used to construct a {@link - * io.netty.bootstrap.Bootstrap}. - */ @Provides - @Singleton - Class provideChannelClazz() { - return NioSocketChannel.class; + @HttpWhoisProtocol + ProbingSequence provideHttpWhoisSequence( + @HttpWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** - * {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. - */ @Provides - @Singleton - Duration provideDuration() { - return DEFAULT_DURATION; + @HttpsWhoisProtocol + ProbingSequence provideHttpsWhoisSequence( + @HttpsWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** - * {@link Provides} the {@link SslProvider} used by instances of {@link - * google.registry.monitoring.blackbox.handlers.SslClientInitializer} - */ @Provides - @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } - /** - * Root level {@link Component} that provides each {@link ProbingSequence}. - */ + @Provides + @HttpsWhoisProtocol + int provideHttpsWhoisPort() { + return httpsWhoIsPort; + } + + @Provides + ImmutableMap providePortToProtocolMap( + Set protocolSet) { + return Maps.uniqueIndex(protocolSet, Protocol::port); + } + + + @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, + TokenModule.class }) public interface ProberComponent { - //Standard WebWhois sequence - Set sequences(); + @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); + + @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); + + ImmutableMap providePortToProtocolMap(); + + @WebWhoisProtocol Token provideWebWhoisToken(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2441debb12d..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -34,7 +34,7 @@ import javax.inject.Provider; /** - *Superclass that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -183,4 +183,19 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + @Override + public String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n" + + "path: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host(), + path() + ); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java new file mode 100644 index 00000000000..6387207fea4 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -0,0 +1,122 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.EventLoopGroup; + +/** + * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * + * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} + * but for tests is {@link LocalChannel} + * + *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, + * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * + *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one + * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ */ +public class ProbingSequence { + private ProbingStep firstStep; + + /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ + private EventLoopGroup eventGroup; + + /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ + private Bootstrap bootstrap; + + public Bootstrap getBootstrap() { + return bootstrap; + } + + public void start(Token token) { + // calls the first step with input token; + firstStep.accept(token); + } + + /** + * {@link Builder} which takes in {@link ProbingStep}s + * + * @param Same specified {@code C} for overall {@link ProbingSequence} + */ + public static class Builder { + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstSequenceStep; + private EventLoopGroup eventLoopGroup; + private Class classType; + + Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; + return this; + } + + Builder addStep(ProbingStep step) { + if (currentStep == null) { + firstStep = step; + } else { + currentStep.nextStep(step); + } + currentStep = step; + return this; + } + + /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ + Builder makeFirstRepeated() { + firstSequenceStep = currentStep; + return this; + } + /** Set the class to be the same as {@code C} */ + public Builder setClass(Class classType) { + this.classType = classType; + return this; + } + + public ProbingSequence build() { + currentStep.nextStep(firstSequenceStep); + currentStep.lastStep(); + return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + } + + } + + /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ + private void setParents() { + ProbingStep currentStep = firstStep.parent(this).nextStep(); + + while (currentStep != firstStep) { + currentStep = currentStep.parent(this).nextStep(); + } + } + private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, + Class classType) { + this.firstStep = firstStep; + this.eventGroup = eventLoopGroup; + this.bootstrap = new Bootstrap() + .group(eventGroup) + .channel(classType); + setParents(); + } + + @Override + public String toString() { + return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); + + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java new file mode 100644 index 00000000000..5bad5abf6bf --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -0,0 +1,170 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.io.IOException; +import java.util.function.Consumer; +import org.joda.time.Duration; + +/** + * Represents generator of actions performed at each step in {@link ProbingSequence} + * + * @param See {@code C} in {@link ProbingSequence} + * + *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are + * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies + * these components on each loop iteration with the consumed {@link Token} and from that, + * generates new {@link ProbingAction} to perform<./p> + * + *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

+ */ +public abstract class ProbingStep implements Consumer { + + public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); + protected static final Duration DEFAULT_DURATION = new Duration(2000L); + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + protected LocalAddress address = DEFAULT_ADDRESS; + + /** Necessary boolean to inform when to obtain next {@link Token}*/ + private boolean isLastStep = false; + private ProbingStep nextStep; + private ProbingSequence parent; + + protected Duration duration; + + protected final Protocol protocol; + protected final OutboundMessageType message; + + protected ProbingStep(Protocol protocol, OutboundMessageType message) { + this.protocol = protocol; + this.message = message; + } + + private OutboundMessageType message() { + return message; + } + + Protocol protocol() { + return protocol; + } + + + void lastStep() { + isLastStep = true; + } + + void nextStep(ProbingStep step) { + this.nextStep = step; + } + + ProbingStep nextStep() { + return this.nextStep; + } + + ProbingStep parent(ProbingSequence parent) { + this.parent = parent; + return this; + } + + /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + private ProbingAction generateAction(Token token) throws InternalException { + ProbingAction generatedAction; + + OutboundMessageType message = token.modifyMessage(message()); + + //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction + if (protocol().persistentConnection() && token.channel() != null) { + generatedAction = ExistingChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .channel(token.channel()) + .build(); + } else { + generatedAction = NewChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .bootstrap(parent.getBootstrap()) + .address(address) + .build(); + + } + return generatedAction; + } + + + /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + private Token generateNextToken(Token token) { + return (isLastStep) ? token.next() : token; + } + + @Override + public void accept(Token token) { + ProbingAction nextAction; + //attempt to generate new action. On error, move on to next step + try { + nextAction = generateAction(token); + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Generation"); + nextStep.accept(generateNextToken(token)); + return; + } + + //If the next step maintains the connection, pass on the channel from this + if (protocol().persistentConnection()) { + token.channel(nextAction.channel()); + } + + //call the created action + ChannelFuture future = nextAction.call(); + + //On result, either log success and move on, or + future.addListener(f -> { + if (f.isSuccess()) { + logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); + nextStep.accept(generateNextToken(token)); + } else { + logger.atSevere().withCause(f.cause()).log("Did not result in future success"); + } + }); + } + + @Override + public String toString() { + return String.format("ProbingStep with Protocol: %s\n" + + "OutboundMessage: %s\n" + + "and parent sequence: %s", + protocol(), + message(), + parent); + } + +} + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 2a4a8d0ed76..855d9c5b41a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -54,4 +54,16 @@ public static abstract class Builder { public abstract Protocol build(); } + + @Override + public String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 55fc7cf71a9..dba905c0e49 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,120 +18,90 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; + +import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.time.Duration; -/** - * A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. - */ +/** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; - private static final String HTTP_PROTOCOL_NAME = "http"; - private static final String HTTPS_PROTOCOL_NAME = "https"; - - /** - * Standard length of messages used by Proxy. Equates to 0.5 MB. - */ - private static final int maximumMessageLengthBytes = 512 * 1024; + final static String DOMAIN_SUFFIX = "whois.nic."; - /** - * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. - */ + /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpWhoisProtocol { + @interface HttpWhoisProtocol {} - } + /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ + @Qualifier + @interface HttpsWhoisProtocol {} - /** - * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. - */ + /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier - public @interface HttpsWhoisProtocol { + public @interface WebWhoisProtocol {} - } - /** - * Dagger qualifier to provide any WebWhois related bindings. - */ - @Qualifier - public @interface WebWhoisProtocol { - } + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + - /** - * {@link Provides} standard WebWhois sequence. - */ @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { + @HttpWhoisProtocol + static ProbingStep provideHttpWhoisProbingSequence( + @HttpWhoisProtocol Protocol httpWhoisProtocol) { + return new ProbingStepWeb<>(httpWhoisProtocol); + } - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); + @Provides + @HttpsWhoisProtocol + static ProbingStep provideHttpsWhoisProbingStep( + @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { + return new ProbingStepWeb<>(httpsWhoisProtocol); } - /** - * {@link Provides} only step used in WebWhois sequence. - */ + @Singleton @Provides - @WebWhoisProtocol - static ProbingStep provideWebWhoisStep( - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @WebWhoisProtocol Bootstrap bootstrap, - HttpRequestMessage messageTemplate, - Duration duration) { - - return ProbingStep.builder() - .setProtocol(httpWhoisProtocol) - .setBootstrap(bootstrap) - .setMessageTemplate(messageTemplate) - .setDuration(duration) + @HttpWhoisProtocol + static Protocol provideHttpWhoisProtocol( + @HttpWhoisProtocol int httpWhoisPort, + @HttpWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** - * {@link Provides} the {@link Protocol} that corresponds to http connection. - */ @Singleton @Provides - @HttpWhoisProtocol - static Protocol provideHttpWhoisProtocol( + @IntoSet + static Protocol provideHttpProtocolForSet( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTP_PROTOCOL_NAME) - .setPort(httpWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** - * {@link Provides} the {@link Protocol} that corresponds to https connection. - */ + @Singleton @Provides @HttpsWhoisProtocol @@ -139,24 +109,40 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTPS_PROTOCOL_NAME) - .setPort(httpsWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } + @Singleton + @Provides + @IntoSet + static Protocol provideHttpsProtocolForSet( + @HttpsWhoisProtocol int httpsWhoisPort, + @HttpsWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Provides + @WebWhoisProtocol + String provideHttpWhoisHost() { + return "app"; + } + - /** - * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http - * protocol. - */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -165,18 +151,13 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** - * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https - * protocol. - */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( - @HttpsWhoisProtocol - Provider> sslClientInitializerProvider, + @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -186,67 +167,34 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } - @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); - } - - @Provides - static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { - return new HttpObjectAggregator(maxContentLength); - } - - /** - * {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. - */ - @Provides - @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer( - SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); - } - /** - * {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. - */ - @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap( - EventLoopGroup eventLoopGroup, - Class channelClazz) { - return new Bootstrap() - .group(eventLoopGroup) - .channel(channelClazz); + static MessageHandler provideMessageHandler() { + return new WebWhoisMessageHandler(); } @Provides - @WebWhoisProtocol - int provideMaximumMessageLengthBytes() { - return maximumMessageLengthBytes; + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); } - /** - * {@link Provides} the list of top level domains to be probed - */ - @Singleton @Provides - @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy", "xn--q9jyb4c"); + static HttpObjectAggregator provideHttpObjectAggregator() { + return new HttpObjectAggregator(1048576); } @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return HTTP_WHOIS_PORT; + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } @Provides @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return HTTPS_WHOIS_PORT; + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index dfd88cba1ce..c3622e1b810 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,32 +15,45 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; /** - *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + * Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, + * as it should only be passed in messages that implement the {@link InboundMessageType} interface. * - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} - * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception - * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses - * specify further work to be done for specific kinds of channel pipelines.

+ *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link + * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. + * Second, it stores the {@link OutboundMessageType} passed down the pipeline, so that subclasses + * can use that information for their own processes. Lastly, with any exception thrown, the + * connection is closed, and the ProbingAction governing this channel is informed of the error. + * Subclasses specify further work to be done for specific kinds of channel pipelines. */ public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Three types of responses received down pipeline */ + public enum ResponseType {SUCCESS, FAILURE, ERROR} + + /** Status of response for current {@link ActionHandler} instance */ + private static ResponseType status; + protected ChannelPromise finished; - /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** + * Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized + * {@link ChannelPromise} + */ public ChannelFuture getFuture() { return finished; } @@ -48,25 +61,47 @@ public ChannelFuture getFuture() { /** Initializes new {@link ChannelPromise} */ @Override public void handlerAdded(ChannelHandlerContext ctx) { - //Once handler is added to channel pipeline, initialize channel and future for this handler + // Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws Exception { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { //simply marks finished as success + status = ResponseType.SUCCESS; finished.setSuccess(); } - /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ + /** + * Logs the channel and pipeline that caused error, closes channel, then informs {@link + * ProbingAction} listeners of error + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); + logger.atSevere().withCause(cause).log( + String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), ctx.channel().pipeline().toString())); + + + if (ResponseException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + status = ResponseType.FAILURE; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (ServerSideException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + status = ResponseType.ERROR; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (InternalException.class.isInstance(cause)){ + logger.atSevere().withCause(cause).log("Severe internal error"); + finished.setFailure(cause); + } else { + finished.setFailure(cause); + } - finished.setFailure(cause); + //due to failure, close channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 5b77461cd8f..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -17,20 +17,16 @@ import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; @@ -59,7 +55,7 @@ public WebWhoisActionHandler() {} */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ServerSideException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -67,9 +63,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - finished.setSuccess(); - logger.atInfo().log("Response Received: " + response); + super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -79,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -126,10 +121,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + throw new ResponseException("Response received from remote site was: " + response.status()); } } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 576d6a04d42..4afc5d95ba7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,59 +1,33 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -/** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom - * type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for - * redirection. - */ -public class WebWhoisMessageHandler extends ChannelDuplexHandler { +public class WebWhoisMessageHandler extends MessageHandler { + + private HttpRequestMessage request; @Inject - public WebWhoisMessageHandler() { - } + public WebWhoisMessageHandler() {} - /** - * Retains {@link HttpRequestMessage} and calls super write method. - */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) - throws Exception { - HttpRequestMessage request = (HttpRequestMessage) msg; + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** - * Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link - * InboundMessageType} instance. - */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + FullHttpResponse originalResponse = (FullHttpResponse) msg; - HttpResponseMessage response = new HttpResponseMessage(originalResponse); + InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8fbb55c6339..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,13 +6,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} - * (but needs to implement {@link OutboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion - * from {@link FullHttpRequest} to its type

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -35,6 +14,11 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + + @Override public HttpRequestMessage setUri(String path) { @@ -42,22 +26,16 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - - //creates message based on content found in original request - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - - - //stores headers from request in finalRequest - request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - - return finalRequest; - + HttpRequestMessage output; + if (buf == null) { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + } else { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + } + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 776e7de0824..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,33 +1,11 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} - * (but needs to implement {@link InboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion - * from {@link FullHttpResponse} to its type

- */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -39,20 +17,22 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } - /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); - //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - //stores headers from response in finalResponse - response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); return finalResponse; } + + + } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index 6cfb235d97c..cbcf2fc82b0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,19 +15,20 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -38,85 +39,111 @@ import io.netty.channel.nio.NioEventLoopGroup; import javax.inject.Provider; import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; - /** * Unit tests for {@link ProbingAction} subtypes * *

Attempts to test how well each {@link ProbingAction} works with an {@link ActionHandler} * subtype when receiving to all possible types of responses

- */ + * */ @RunWith(JUnit4.class) public class ProbingActionTest { - - private static final String TEST_MESSAGE = "MESSAGE_TEST"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final int TEST_PORT = 0; - - private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - - /** - * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on - * {@link ProbingAction} - */ + /** Necessary Constants for test */ + private final String TEST_MESSAGE = "MESSAGE_TEST"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final int TEST_PORT = 0; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = () -> testHandler; - private Provider conversionHandlerProvider = () -> conversionHandler; + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - /** - * Used for testing how well probing step can create connection to blackbox server - */ + private ProbingAction newChannelAction; + private ProbingAction existingChannelAction; + private EmbeddedChannel channel; + private Protocol protocol; + + /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); + /** Sets up a {@link Protocol} corresponding to when a new connection is created */ + private void setupNewChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(false) + .build(); + } + /** Sets up a {@link Protocol} corresponding to when a new connection exists */ + private void setupExistingChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(true) + .build(); + } + + /** Sets up a {@link NewChannelAction} with test specified attributes */ + private void setupNewChannelAction() { + newChannelAction = NewChannelAction.builder() + .bootstrap(bootstrap) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .address(address) + .build(); + } + + private void setupChannel() { + channel = new EmbeddedChannel(); + } + + /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + private void setupExistingChannelAction(Channel channel) { + existingChannelAction = ExistingChannelAction.builder() + .channel(channel) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .build(); + } - @Ignore @Test public void testBehavior_existingChannel() { //setup - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up a Protocol corresponding to when a connection exists. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(true) - .build(); + setupChannel(); + setupExistingChannelProtocol(); + setupExistingChannelAction(channel); + channel.pipeline().addLast(conversionHandler); + channel.pipeline().addLast(testHandler); - // Sets up a ProbingAction that creates a channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setChannel(channel) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost("") - .build(); - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = existingChannelAction.call(); - //Obtains the outboundMessage passed through pipeline after delay - Object msg = null; - while (msg == null) { - msg = channel.readOutbound(); - } - //tests the passed message is exactly what we expect + //Ensures that we pass in the right message to the channel and haven't marked the future as success yet + Object msg = channel.readOutbound(); assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - assertThat(request).isEqualTo(TEST_MESSAGE); - - // Ensures that we haven't marked future as done until response is received. - assertThat(future.isDone()).isFalse(); + String response = ((ByteBuf) msg).toString(UTF_8); + assertThat(response).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()).isFalse(); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); @@ -128,41 +155,19 @@ public void testBehavior_existingChannel() { @Test public void testSuccess_newChannel() throws Exception { //setup - - LocalAddress address = new LocalAddress(ADDRESS_NAME); - Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); - - // Sets up a Protocol corresponding to when a new connection is created. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - + setupNewChannelProtocol(); + setupNewChannelAction(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - // Sets up a ProbingAction with existing channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future = future.syncUninterruptibly(); + future.sync(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler) testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()); + assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java new file mode 100644 index 00000000000..7a713017072 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java @@ -0,0 +1,219 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.TestUtils.TestStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.handlers.ConversionHandler; +import google.registry.monitoring.blackbox.handlers.NettyRule; +import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.junit.Rule; +import org.junit.Test; + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + + /** Used for testing how well probing step can create connection to blackbox server */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + + + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ + private ProbingSequence testSequence; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); + dummyStep = new DummyStep(testProtocol, eventLoopGroup); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(false) + .build(); + } + + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(true) + .build(); + } + + /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ + private void setupSequence() { + testSequence = new ProbingSequence.Builder() + .eventLoopGroup(eventLoopGroup) + .setClass(LocalChannel.class) + .addStep(firstStep) + .makeFirstRepeated() + .addStep(dummyStep) + .build(); + } + + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //there should be no next step + assertThat(firstStep.nextStep()).isNull(); + + //we expect that this exception be thrown + assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); + + } + + @Test + public void testWithSequence_NewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupSequence(); + setupNewChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupSequence(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java new file mode 100644 index 00000000000..67e2cb7165d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -0,0 +1,85 @@ +package google.registry.monitoring.blackbox.TestServers; + +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; + +/** + * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + */ +public abstract class TestServer { + private LocalAddress localAddress; + + TestServer(LocalAddress localAddress, ImmutableList handlers) { + this(new NioEventLoopGroup(1), localAddress, handlers); + } + + TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + this.localAddress = localAddress; + + //Creates ChannelInitializer with handlers specified + ChannelInitializer serverInitializer = new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) { + for (ChannelHandler handler : handlers) { + ch.pipeline().addLast(handler); + } + } + }; + //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using LocalServerChannel class + ServerBootstrap serverBootstrap = + new ServerBootstrap() + .group(eventLoopGroup) + .channel(LocalServerChannel.class) + .childHandler(serverInitializer); + + ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); + + } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** Saves any inbound error as the cause of the promise failure. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java new file mode 100644 index 00000000000..ab9997b6c68 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -0,0 +1,92 @@ +package google.registry.monitoring.blackbox.TestServers; + +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpServerCodec; + +/** + * {@link TestServer} subtype that performs WebWhois Services Expected + * + * It will either redirect the client to the correct location if given the + * requisite redirect input, give the client a successful response if they give + * the expected final destination, or give the client an error message if given + * an unexpected host location + */ +public class WebWhoisServer extends TestServer { + + public WebWhoisServer(LocalAddress localAddress, ImmutableList handlers) { + super(localAddress, handlers); + } + + public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + super(eventLoopGroup, localAddress, handlers); + } + + /** Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the HttpRequestMessage object through pipeline */ + public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + return new WebWhoisServer( + eventLoopGroup, + localAddress, + ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) + ); + } + /** Creates server that sends exactly what we expect a remote server to send as a response, by sending the {@link ByteBuf} of the response through pipeline */ + public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + return new WebWhoisServer( + eventLoopGroup, + localAddress, + ImmutableList.of( + new HttpServerCodec(), + new HttpObjectAggregator(1048576), + new RedirectHandler(redirectInput, destinationInput)) + ); + } + + /** + * Handler that will wither redirect client, give successful response, or give error messge + */ + @Sharable + static class RedirectHandler extends ChannelDuplexHandler { + private String redirectInput; + private String destinationInput; + + /** + * + * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + */ + public RedirectHandler(String redirectInput, String destinationInput) { + this.redirectInput = redirectInput; + this.destinationInput = destinationInput; + } + + /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + HttpRequest request = (HttpRequest) msg; + HttpResponse response; + if (request.headers().get("host").equals(redirectInput)) { + response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + } else if (request.headers().get("host").equals(destinationInput)) { + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + } else { + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + } + ctx.channel().writeAndFlush(response); + + } + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java new file mode 100644 index 00000000000..8d1722c9625 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -0,0 +1,252 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.US_ASCII; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.joda.time.Duration; + +/** Utility class for various helper methods used in testing. */ +public class TestUtils { + + static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + + public static FullHttpRequest makeHttpGetRequest(String host, String path) { + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); + request.headers().set("host", host).setInt("content-length", 0); + return request; + } + + public static FullHttpResponse makeHttpResponse(String content, HttpResponseStatus status) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buf); + response.headers().setInt("content-length", buf.readableBytes()); + return response; + } + + public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status); + response.headers().setInt("content-length", 0); + return response; + } + + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + public static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; + } + + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); + return response; + } + + /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ + public static class TestProvider implements Provider { + + private E obj; + + public TestProvider(E obj) { + this.obj = obj; + } + + @Override + public E get() { + return obj; + } + } + + /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ + public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { + + String message; + + public DuplexMessageTest() { + message = ""; + } + + public DuplexMessageTest(String msg) { + message = msg; + } + + @Override + public String toString() { + return message; + } + } + + /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ + public static class TestStep extends ProbingStep { + + public TestStep(Protocol protocol, String testMessage, LocalAddress address) { + super(protocol, new DuplexMessageTest(testMessage)); + this.address = address; + this.duration = Duration.ZERO; + } + } + + /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ + public static class DummyStep extends ProbingStep { + private DefaultPromise future; + + public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { + super(protocol, new DuplexMessageTest()); + future = new DefaultPromise(eventLoopGroup.next()) {}; + duration = Duration.ZERO; + } + + @Override + public void accept(Token token) { + future.setSuccess(token); + } + public DefaultPromise getFuture() { + return future; + } + } + + /** Basic outline for {@link Token} instances to be used in tests */ + private static abstract class TestToken extends Token { + private String host; + + protected TestToken(String host) { + this.host = host; + } + @Override + public Token next() { + return this; + } + + @Override + public OutboundMessageType modifyMessage(OutboundMessageType message) { + return message; + } + + @Override + public String getHost() { + return host; + } + + } + + /** {@link TestToken} instance that creates new channel */ + public static class NewChannelToken extends TestToken { + public NewChannelToken(String host) { + super(host); + } + @Override + public Channel channel() { + return null; + } + } + + /** {@link TestToken} instance that passes in existing channel */ + public static class ExistingChannelToken extends TestToken { + private Channel channel; + + public ExistingChannelToken(Channel channel, String host) { + super(host); + this.channel = channel; + } + @Override + public Channel channel() { + return channel; + } + } + + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java new file mode 100644 index 00000000000..ef5cba5b60d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -0,0 +1,60 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + */ +@RunWith(JUnit4.class) +public class TokenTest { + + private static String PREFIX = "whois.nic."; + private static String TEST_STARTER = "starter"; + private static String TEST_DOMAIN = "test"; + + public Token webToken = new WebWhoisToken(TEST_DOMAIN); + + @Test + public void testWebToken_MessageModificationSuccess() { + //creates Request message with header + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + message.headers().set("host", TEST_STARTER); + + //attempts to use Token's method for modifying the method based on its stored host + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { + throw new RuntimeException(e); + } + + + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 987abbfd7dc..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,38 +17,31 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link - * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to + * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** - * Handles inbound conversion - */ + /** Handles inbound conversion */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } - /** - * Handles outbound conversion - */ + /** Handles outbound conversion */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java new file mode 100644 index 00000000000..b6b5e8fbe0c --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -0,0 +1,201 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.truth.Truth.assertThat; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.truth.ThrowableSubject; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.ReferenceCountUtil; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import org.junit.rules.ExternalResource; + +/** + * Helper for setting up and testing client / server connection with netty. + * + *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ */ +public final class NettyRule extends ExternalResource { + + + + // All I/O operations are done inside the single thread within this event loop group, which is + // different from the main test thread. Therefore synchronizations are required to make sure that + // certain I/O activities are finished when assertions are performed. + public NettyRule() { + eventLoopGroup = new NioEventLoopGroup(1); + } + public NettyRule(EventLoopGroup e) { + eventLoopGroup = e; + } + private final EventLoopGroup eventLoopGroup; + private WebWhoisServer webWhoisServer; + + // Handler attached to server's channel to record the request received. + private EchoHandler echoHandler; + + // Handler attached to client's channel to record the response received. + private DumpHandler dumpHandler; + + private Channel channel; + + /** Sets up a server channel bound to the given local address. */ + public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + checkState(echoHandler == null, "Can't call setUpServer twice"); + echoHandler = new EchoHandler(); + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + } + + /** Sets up a client channel connecting to the give local address. */ + void setUpClient( + LocalAddress localAddress, + ProbingAction probingAction, + ChannelHandler handler) { + checkState(echoHandler != null, "Must call setUpServer before setUpClient"); + checkState(dumpHandler == null, "Can't call setUpClient twice"); + dumpHandler = new DumpHandler(); + ChannelInitializer clientInitializer = + new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) throws Exception { + // Add the given handler + ch.pipeline().addLast(handler); + // Add the "dumpHandler" last to log the incoming message + ch.pipeline().addLast(dumpHandler); + } + }; + Bootstrap b = + new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class) + .handler(clientInitializer) + .attr(PROBING_ACTION_KEY, probingAction); + channel = b.connect(localAddress).syncUninterruptibly().channel(); + } + + private void checkReady() { + checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); + } + + /** Test that custom setup to send message to current server sends right message */ + public void assertThatCustomWorks(String message) throws Exception { + assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); + + } + + /** + * Test that a message can go through, both inbound and outbound. + * + *

The client writes the message to the server, which echos it back and saves the string in its + * promise. The client receives the echo and saves it in its promise. All these activities happens + * in the I/O thread, and this call itself returns immediately. + */ + void assertThatMessagesWork() throws Exception { + checkReady(); + assertThat(channel.isActive()).isTrue(); + + writeToChannelAndFlush(channel, "Hello, world!"); + assertThat(echoHandler.getRequestFuture().get()).isEqualTo("Hello, world!"); + assertThat(dumpHandler.getResponseFuture().get()).isEqualTo("Hello, world!"); + } + + Channel getChannel() { + checkReady(); + return channel; + } + + ThrowableSubject assertThatServerRootCause() { + checkReady(); + return assertThat( + Throwables.getRootCause( + assertThrows(ExecutionException.class, () -> echoHandler.getRequestFuture().get()))); + } + + ThrowableSubject assertThatClientRootCause() { + checkReady(); + return assertThat( + Throwables.getRootCause( + assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); + } + + + + /** A handler that dumps its inbound message to a promise that can be inspected later. */ + private static class DumpHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture responseFuture = new CompletableFuture<>(); + + Future getResponseFuture() { + return responseFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + assertThat(msg).isInstanceOf(ByteBuf.class); + String response = ((ByteBuf) msg).toString(UTF_8); + // There is no more use of this message, we should release its reference count so that it + // can be more effectively garbage collected by Netty. + ReferenceCountUtil.release(msg); + // Save the string in the promise and make it as complete. + responseFuture.complete(response); + } + + /** Saves any inbound error into the failure cause of the promise. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); + } + } + + @Override + protected void after() { + Future unusedFuture = eventLoopGroup.shutdownGracefully(); + } + + private static void writeToChannelAndFlush(Channel channel, String data) { + ChannelFuture unusedFuture = + channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java new file mode 100644 index 00000000000..469c62a8f75 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -0,0 +1,233 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; +import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; +import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.ExistingChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SniHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslProvider; +import io.netty.handler.ssl.util.SelfSignedCertificate; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.cert.CertPathBuilderException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLException; +import org.joda.time.Duration; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +/** + * Unit tests for {@link SslClientInitializer}. + * + *

To validate that the handler accepts & rejects connections as expected, a test server and a + * test client are spun up, and both connect to the {@link LocalAddress} within the JVM. This avoids + * the overhead of routing traffic through the network layer, even if it were to go through + * loopback. It also alleviates the need to pick a free port to use. + * + *

The local addresses used in each test method must to be different, otherwise tests run in + * parallel may interfere with each other. + */ +@RunWith(Parameterized.class) +public class SslClientInitializerTest { + + private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); + + /** Fake host to test if the SSL engine gets the correct peer host. */ + private static final String SSL_HOST = "www.example.tld"; + + /** Fake port to test if the SSL engine gets the correct peer port. */ + private static final int SSL_PORT = 12345; + + @Rule + public NettyRule nettyRule = new NettyRule(); + + @Parameter(0) + public SslProvider sslProvider; + + // We do our best effort to test all available SSL providers. + @Parameters(name = "{0}") + public static SslProvider[] data() { + return OpenSsl.isAvailable() + ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[] {SslProvider.JDK}; + } + + /** Saves the SNI hostname received by the server, if sent by the client. */ + private String sniHostReceived; + + /** Fake protocol saved in channel attribute. */ + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .persistentConnection(false) + .build(); + + private ProbingAction probingAction; + + private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) + throws Exception { + SslContext sslContext = SslContextBuilder.forServer(privateKey, certificate).build(); + return new SniHandler( + hostname -> { + sniHostReceived = hostname; + return sslContext; + }); + } + + private void setupProbingAction(Channel channel) { + probingAction = ExistingChannelAction.builder() + .delay(Duration.ZERO) + .host(SSL_HOST) + .channel(channel) + .outboundMessage(DEFAULT_MESSAGE) + .protocol(PROTOCOL) + .build(); + } + + @Test + public void testSuccess_swappedInitializerWithSslHandler() throws Exception { + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider); + EmbeddedChannel channel = new EmbeddedChannel(); + setupProbingAction(channel); + channel.attr(PROBING_ACTION_KEY).set(probingAction); + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(sslClientInitializer); + ChannelHandler firstHandler = pipeline.first(); + assertThat(firstHandler.getClass()).isEqualTo(SslHandler.class); + SslHandler sslHandler = (SslHandler) firstHandler; + assertThat(sslHandler.engine().getPeerHost()).isEqualTo(SSL_HOST); + assertThat(sslHandler.engine().getPeerPort()).isEqualTo(SSL_PORT); + assertThat(channel.isActive()).isTrue(); + } + + @Test + public void testSuccess_protocolAttributeNotSet() { + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider); + EmbeddedChannel channel = new EmbeddedChannel(); + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(sslClientInitializer); + // Channel initializer swallows error thrown, and closes the connection. + assertThat(channel.isActive()).isFalse(); + } + + @Test + public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Exception { + SelfSignedCertificate ssc = new SelfSignedCertificate(SSL_HOST); + LocalAddress localAddress = + new LocalAddress("DEFAULT_TRUST_MANAGER_REJECT_SELF_SIGNED_CERT_" + sslProvider); + nettyRule.setUpServer(localAddress, getServerHandler(ssc.key(), ssc.cert())); + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider); + + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + // The connection is now terminated, both the client side and the server side should get + // exceptions. + nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); + nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); + assertThat(nettyRule.getChannel().isActive()).isFalse(); + } + + @Test + public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws Exception { + LocalAddress localAddress = + new LocalAddress("CUSTOM_TRUST_MANAGER_ACCEPT_CERT_SIGNED_BY_TRUSTED_CA_" + sslProvider); + + // Generate a new key pair. + KeyPair keyPair = getKeyPair(); + + // Generate a self signed certificate, and use it to sign the key pair. + SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Certificate cert = signKeyPair(ssc, keyPair, SSL_HOST); + + // Set up the server to use the signed cert and private key to perform handshake; + PrivateKey privateKey = keyPair.getPrivate(); + nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); + + // Set up the client to trust the self signed cert used to sign the cert that server provides. + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + + setUpSslChannel(nettyRule.getChannel(), cert); + nettyRule.assertThatMessagesWork(); + + // Verify that the SNI extension is sent during handshake. + assertThat(sniHostReceived).isEqualTo(SSL_HOST); + } + + @Test + public void testFailure_customTrustManager_wrongHostnameInCertificate() throws Exception { + LocalAddress localAddress = + new LocalAddress("CUSTOM_TRUST_MANAGER_WRONG_HOSTNAME_" + sslProvider); + + // Generate a new key pair. + KeyPair keyPair = getKeyPair(); + + // Generate a self signed certificate, and use it to sign the key pair. + SelfSignedCertificate ssc = new SelfSignedCertificate(); + X509Certificate cert = signKeyPair(ssc, keyPair, "wrong.com"); + + // Set up the server to use the signed cert and private key to perform handshake; + PrivateKey privateKey = keyPair.getPrivate(); + nettyRule.setUpServer(localAddress, getServerHandler(privateKey, cert)); + + // Set up the client to trust the self signed cert used to sign the cert that server provides. + SslClientInitializer sslClientInitializer = + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + + // When the client rejects the server cert due to wrong hostname, both the client and server + // should throw exceptions. + nettyRule.assertThatClientRootCause().isInstanceOf(CertificateException.class); + nettyRule.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST); + nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class); + assertThat(nettyRule.getChannel().isActive()).isFalse(); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java new file mode 100644 index 00000000000..68b2919141d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslInitializerTestUtils.java @@ -0,0 +1,95 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +import static com.google.common.truth.Truth.assertThat; + +import io.netty.channel.Channel; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.util.SelfSignedCertificate; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import javax.net.ssl.SSLSession; +import javax.security.auth.x500.X500Principal; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.x509.X509V3CertificateGenerator; + +/** + * Utility class that provides methods used by {@link SslClientInitializerTest} + */ +public class SslInitializerTestUtils { + + static { + Security.addProvider(new BouncyCastleProvider()); + } + + public static KeyPair getKeyPair() throws Exception { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); + keyPairGenerator.initialize(2048, new SecureRandom()); + return keyPairGenerator.generateKeyPair(); + } + + /** + * Signs the given key pair with the given self signed certificate. + * + * @return signed public key (of the key pair) certificate + */ + public static X509Certificate signKeyPair( + SelfSignedCertificate ssc, KeyPair keyPair, String hostname) throws Exception { + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + X500Principal dnName = new X500Principal("CN=" + hostname); + certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); + certGen.setSubjectDN(dnName); + certGen.setIssuerDN(ssc.cert().getSubjectX500Principal()); + certGen.setNotBefore(Date.from(Instant.now().minus(Duration.ofDays(1)))); + certGen.setNotAfter(Date.from(Instant.now().plus(Duration.ofDays(1)))); + certGen.setPublicKey(keyPair.getPublic()); + certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); + return certGen.generate(ssc.key(), "BC"); + } + + /** + * Verifies tha the SSL channel is established as expected, and also sends a message to the server + * and verifies if it is echoed back correctly. + * + * @param certs The certificate that the server should provide. + * @return The SSL session in current channel, can be used for further validation. + */ + static SSLSession setUpSslChannel( + Channel channel, + X509Certificate... certs) + throws Exception { + SslHandler sslHandler = channel.pipeline().get(SslHandler.class); + // Wait till the handshake is complete. + sslHandler.handshakeFuture().get(); + + assertThat(channel.isActive()).isTrue(); + assertThat(sslHandler.handshakeFuture().isSuccess()).isTrue(); + assertThat(sslHandler.engine().getSession().isValid()).isTrue(); + assertThat(sslHandler.engine().getSession().getPeerCertificates()) + .asList() + .containsExactlyElementsIn(certs); + // Returns the SSL session for further assertion. + return sslHandler.engine().getSession(); + } +} + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 19e608c97d2..518bb9ba686 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,27 +14,26 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; /** - * Concrete implementation of {@link ActionHandler} that does nothing different from parent class - * other than store and return the {@code inboundMessage} + * Concrete implementation of {@link ActionHandler} that does nothing different from + * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ - private InboundMessageType receivedMessage; + private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage; + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } - public InboundMessageType getResponse() { + @Override + public String toString() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 63bb2cf5b53..71d8d66b6c0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,32 +15,45 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; +import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ +/** + * Unit tests for {@link WebWhoisActionHandler}. + * + *

Attempts to test how well {@link WebWhoisActionHandler} works + * when responding to all possible types of responses

+ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; @@ -50,80 +63,85 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; + private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); + private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - + private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; + private ProbingAction probingAction; + private Provider actionHandlerProvider; + private void generateLocalAddress() { + address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + } /** Creates default protocol with empty list of handlers and specified other inputs */ private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() .name(name) .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); + .handlerProviders(ImmutableList.of(actionHandlerProvider)) + .persistentConnection(false) + .build(); } /** Initializes new WebWhoisActionHandler */ private void setupActionHandler() { actionHandler = new WebWhoisActionHandler(); + actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); + private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + setupProbingActionBasic( + protocol, + outboundMessage, + makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); } + private Bootstrap makeBootstrap(EventLoopGroup group) { + return new Bootstrap() + .group(group) + .channel(LocalChannel.class); + } /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() + private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + probingAction = NewChannelAction.builder() .protocol(protocol) .outboundMessage(outboundMessage) .delay(DEFAULT_DURATION) .bootstrap(bootstrap) + .host(TARGET_HOST) + .address(DEFAULT_ADDRESS) .build(); } - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); + private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(host) + .address(address) + .build(); } - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; + private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testSuccess_responseOk() { + public void testBasic_responseOk() throws Exception { //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); - + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); @@ -146,10 +164,13 @@ public void testSuccess_responseOk() { } @Test - public void testSuccess_responseBad() { + public void testBasic_responseFailure() { //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseBad", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); @@ -158,7 +179,8 @@ public void testSuccess_responseBad() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + FullHttpResponse response = HttpResponseMessage + .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -172,19 +194,57 @@ public void testSuccess_responseBad() { //ensures Protocol is the same assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } + @Test + public void testBasic_responseError() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseError", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + + //stores future + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, and event is success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + } @Test - public void testSuccess_redirectCloseChannel() { + public void testBasic_redirectCloseChannel() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); + HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", 0); + generateLocalAddress(); + setupChannel(initialProtocol, outboundMessage); //stores future ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + //checks that future has not been set to successful or a failure + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); @@ -195,27 +255,69 @@ public void testSuccess_redirectCloseChannel() { } @Test - public void testSuccess_redirectHost() { + public void testBasic_redirectHost() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); channel.writeInbound(originalResponse); + ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); + Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); + assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); + } + + @Test + public void testAdvanced_responseOk() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", TARGET_HOST, group); + //stores future + ChannelFuture future = probingAction.call(); + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + } + + @Test + public void testAdvanced_responseFailure() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", TARGET_HOST, group); + + //stores future + ChannelFuture future = probingAction.call(); + + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } } + From 867a3795d8c748f82f643416d94ea178004ebb97 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 176/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 +++++++++----- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/ProbingSequence.java | 1 - .../monitoring/blackbox/ProbingStep.java | 7 +--- .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 - .../monitoring/blackbox/Tokens/Token.java | 4 +- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../monitoring/blackbox/WebWhoisModule.java | 2 +- .../exceptions/EppClientException.java | 29 ------------- .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++- .../handlers/WebWhoisMessageHandler.java | 22 +++++++++- .../blackbox/messages/HttpRequestMessage.java | 41 +++++++++++++------ .../messages/HttpResponseMessage.java | 26 ++++++++---- .../blackbox/messages/InboundMessageType.java | 1 - .../messages/OutboundMessageType.java | 1 - .../blackbox/TestServers/TestServer.java | 16 +++++++- .../blackbox/TestServers/WebWhoisServer.java | 18 +++++++- 20 files changed, 145 insertions(+), 86 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6387207fea4..2eb90a1d6c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -119,4 +119,3 @@ public String toString() { } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 5bad5abf6bf..80b04a3d0c9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.exceptions.EppClientException; import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; import io.netty.channel.local.LocalAddress; -import java.io.IOException; + import java.util.function.Consumer; import org.joda.time.Duration; @@ -164,7 +162,4 @@ public String toString() { message(), parent); } - } - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 855d9c5b41a..0fc3a3e09c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -66,4 +66,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dba905c0e49..7200a1877e2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -197,4 +197,4 @@ static SslClientInitializer provideSslClientInitializer(SslPro } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 4afc5d95ba7..0acf223eb9e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; @@ -8,6 +22,11 @@ import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; +/** + * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} + * in case of reuse for redirection + */ public class WebWhoisMessageHandler extends MessageHandler { private HttpRequestMessage request; @@ -15,6 +34,7 @@ public class WebWhoisMessageHandler extends MessageHandler { @Inject public WebWhoisMessageHandler() {} + /** Retains {@link HttpRequestMessage} and calls super write method*/ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { request = (HttpRequestMessage) msg; @@ -23,9 +43,9 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) } + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - FullHttpResponse originalResponse = (FullHttpResponse) msg; InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..b06938d80a1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +31,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,16 +38,19 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + + request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + + return finalRequest; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..283b14440ac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,7 +33,7 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); @@ -26,13 +43,8 @@ public static HttpResponseMessage fromResponse(FullHttpResponse response) { else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); return finalResponse; } - - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 0c1260becf2..578526933ba 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ public interface InboundMessageType {} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 0dd17e9d4a9..2d5df10f8c1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType {} - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 67e2cb7165d..a4474b6b8b5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static com.google.common.truth.Truth.assertThat; @@ -20,7 +34,7 @@ import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { private LocalAddress localAddress; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index ab9997b6c68..06b19ea3607 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -20,10 +34,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - * It will either redirect the client to the correct location if given the + *

It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location + * an unexpected host location

*/ public class WebWhoisServer extends TestServer { From 9d0352660ea5db3252d11d6867b5b5dd7535f6f6 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 177/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 --- .../monitoring/blackbox/NewChannelAction.java | 144 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProberModule.java | 80 ++--- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingSequence.java | 130 ++++----- .../monitoring/blackbox/ProbingStep.java | 147 +++++----- .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/Protocol.java | 19 +- .../monitoring/blackbox/TokenModule.java | 35 --- .../monitoring/blackbox/Tokens/Token.java | 47 --- .../blackbox/Tokens/WebWhoisToken.java | 54 ---- .../monitoring/blackbox/WebWhoisModule.java | 169 ++++++----- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/ActionHandler.java | 105 +++++-- .../blackbox/handlers/MessageHandler.java | 24 -- .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../handlers/WebWhoisMessageHandler.java | 17 +- .../blackbox/messages/HttpRequestMessage.java | 46 ++- .../messages/HttpResponseMessage.java | 14 +- .../messages/OutboundMessageType.java | 11 +- .../monitoring/blackbox/tokens/Token.java | 43 +-- .../blackbox/tokens/WebWhoisToken.java | 62 ++-- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 32 files changed, 715 insertions(+), 973 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 73bd9127852..0daaf16ded4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,99 +14,59 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; import javax.inject.Singleton; +import org.joda.time.Duration; /** - * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} - * - *

Provides

+ * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores + * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. */ @Module public class ProberModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; + /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + private static final Duration DEFAULT_DURATION = new Duration(4000L); + + /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides - @HttpWhoisProtocol - ProbingSequence provideHttpWhoisSequence( - @HttpWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpsWhoisProtocol - ProbingSequence provideHttpsWhoisSequence( - @HttpsWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return httpWhoIsPort; - } - - @Provides - @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return httpsWhoIsPort; + @Singleton + Duration provideDuration() { + return DEFAULT_DURATION; } + /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - ImmutableMap providePortToProtocolMap( - Set protocolSet) { - return Maps.uniqueIndex(protocolSet, Protocol::port); + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - - + /** Root level {@link Component} that provides each {@link ProbingSequence}. */ @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, - TokenModule.class }) public interface ProberComponent { - @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); - - @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); - - ImmutableMap providePortToProtocolMap(); - - @WebWhoisProtocol Token provideWebWhoisToken(); + //Standard WebWhois sequence + @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2eb90a1d6c3..2dbf48256f9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,108 +14,100 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} - * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ - private EventLoopGroup eventGroup; + /**Each {@link ProbingSequence} requires a start token to begin running. */ + private Token startToken; - /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ - private Bootstrap bootstrap; - - public Bootstrap getBootstrap() { - return bootstrap; - } - - public void start(Token token) { - // calls the first step with input token; - firstStep.accept(token); + public void start() { + // calls the first step with startToken; + firstStep.accept(startToken); } /** - * {@link Builder} which takes in {@link ProbingStep}s - * - * @param Same specified {@code C} for overall {@link ProbingSequence} + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. */ - public static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstSequenceStep; - private EventLoopGroup eventLoopGroup; - private Class classType; - - Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public static class Builder { + + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstRepeatedStep; + private Bootstrap bootstrap; + private Token startToken; + + /** + * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. + * + *

Must be called before adding {@link ProbingStep.Builder}s.

+ */ + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } + + /** Adds start token that activate {@link ProbingSequence}. */ + public Builder addToken(Token token) { + startToken = token; return this; } - Builder addStep(ProbingStep step) { - if (currentStep == null) { + /** + * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * built, and pointed to by the previous {@link ProbingStep} added. + */ + public Builder addStep(ProbingStep.Builder stepBuilder) { + assert (bootstrap != null); + ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + + if (currentStep == null) firstStep = step; - } else { + else currentStep.nextStep(step); - } + currentStep = step; return this; } - /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ - Builder makeFirstRepeated() { - firstSequenceStep = currentStep; - return this; - } - /** Set the class to be the same as {@code C} */ - public Builder setClass(Class classType) { - this.classType = classType; + /** We take special note of the first repeated step. */ + public Builder markFirstRepeated() { + firstRepeatedStep = currentStep; return this; } - public ProbingSequence build() { - currentStep.nextStep(firstSequenceStep); + /** + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and + * calls private constructor to create {@link ProbingSequence}. + */ + public ProbingSequence build() { + if (firstRepeatedStep == null) + firstRepeatedStep = firstStep; + + currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); - return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + return new ProbingSequence(this.firstStep, this.startToken); } - } - /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ - private void setParents() { - ProbingStep currentStep = firstStep.parent(this).nextStep(); - - while (currentStep != firstStep) { - currentStep = currentStep.parent(this).nextStep(); - } - } - private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, - Class classType) { + private ProbingSequence(ProbingStep firstStep, Token startToken) { this.firstStep = firstStep; - this.eventGroup = eventLoopGroup; - this.bootstrap = new Bootstrap() - .group(eventGroup) - .channel(classType); - setParents(); - } - - @Override - public String toString() { - return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); - + this.startToken = startToken; } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 80b04a3d0c9..d54acef325a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,152 +14,145 @@ package google.registry.monitoring.blackbox; +import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.local.LocalAddress; - import java.util.function.Consumer; import org.joda.time.Duration; /** - * Represents generator of actions performed at each step in {@link ProbingSequence} - * - * @param See {@code C} in {@link ProbingSequence} + * {@link AutoValue} class that represents generator of actions performed at each step + * in {@link ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies - * these components on each loop iteration with the consumed {@link Token} and from that, - * generates new {@link ProbingAction} to perform<./p> + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. + * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, + * generates a new {@link ProbingAction} to call.

* - *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -public abstract class ProbingStep implements Consumer { +@AutoValue +public abstract class ProbingStep implements Consumer { - public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); - protected static final Duration DEFAULT_DURATION = new Duration(2000L); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - protected LocalAddress address = DEFAULT_ADDRESS; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ private boolean isLastStep = false; - private ProbingStep nextStep; - private ProbingSequence parent; + private ProbingStep nextStep; - protected Duration duration; + abstract Duration duration(); + abstract Protocol protocol(); + abstract OutboundMessageType messageTemplate(); + abstract Bootstrap bootstrap(); - protected final Protocol protocol; - protected final OutboundMessageType message; - protected ProbingStep(Protocol protocol, OutboundMessageType message) { - this.protocol = protocol; - this.message = message; - } + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder setDuration(Duration value); - private OutboundMessageType message() { - return message; - } + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); - Protocol protocol() { - return protocol; + public abstract ProbingStep build(); } + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - ProbingStep parent(ProbingSequence parent) { - this.parent = parent; - return this; - } - - /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ private ProbingAction generateAction(Token token) throws InternalException { - ProbingAction generatedAction; - - OutboundMessageType message = token.modifyMessage(message()); - - //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction - if (protocol().persistentConnection() && token.channel() != null) { - generatedAction = ExistingChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .channel(token.channel()) - .build(); - } else { - generatedAction = NewChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .bootstrap(parent.getBootstrap()) - .address(address) - .build(); - - } - return generatedAction; + OutboundMessageType message = token.modifyMessage(messageTemplate()); + ProbingAction.Builder probingActionBuilder = ProbingAction.builder() + .setDelay(duration()) + .setProtocol(protocol()) + .setOutboundMessage(message) + .setHost(token.getHost()) + .setBootstrap(bootstrap()); + + if (token.channel() != null) + probingActionBuilder.setChannel(token.channel()); + + return probingActionBuilder.build(); } - /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } @Override public void accept(Token token) { - ProbingAction nextAction; + ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - nextAction = generateAction(token); + currentAction = generateAction(token); } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - //If the next step maintains the connection, pass on the channel from this - if (protocol().persistentConnection()) { - token.channel(nextAction.channel()); - } + //call the created action - ChannelFuture future = nextAction.call(); + ChannelFuture future; + + try { + future = currentAction.call(); + + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Performed"); + nextStep.accept(generateNextToken(token)); + return; + } + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - nextStep.accept(generateNextToken(token)); + //If the next step maintains the connection, pass on the channel from this } else { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + token.setChannel(currentAction.channel()); + + nextStep.accept(generateNextToken(token)); + + }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n" + - "and parent sequence: %s", + "OutboundMessage: %s\n", protocol(), - message(), - parent); + messageTemplate().getClass().getName()); } + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 0fc3a3e09c3..ef52cb9c4bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -17,14 +17,18 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import io.netty.channel.ChannelHandler; +import io.netty.util.AttributeKey; import javax.inject.Provider; /** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. */ @AutoValue public abstract class Protocol { + /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + abstract String name(); public abstract int port(); @@ -35,22 +39,21 @@ public abstract class Protocol { /** Boolean that notes if connection associated with Protocol is persistent.*/ abstract boolean persistentConnection(); - public abstract Builder toBuilder(); - public static Builder builder() { return new AutoValue_Protocol.Builder(); } + /** Builder for {@link Protocol}. */ @AutoValue.Builder - public static abstract class Builder { + public abstract static class Builder { - public abstract Builder name(String value); + public abstract Builder setName(String value); - public abstract Builder port(int num); + public abstract Builder setPort(int num); - public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder setHandlerProviders(ImmutableList> providers); - public abstract Builder persistentConnection(boolean value); + public abstract Builder setPersistentConnection(boolean value); public abstract Protocol build(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 7200a1877e2..dcc9635beaa 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,62 +17,86 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; -import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandler; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - final static String DOMAIN_SUFFIX = "whois.nic."; + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + private static final String DOMAIN_PREFIX = "whois.nic."; + + /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + private static final int maximumMessageLengthBytes = 512 * 1024; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - - - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - - + /** {@link Provides} standard WebWhois sequence. */ @Provides - @HttpWhoisProtocol - static ProbingStep provideHttpWhoisProbingSequence( - @HttpWhoisProtocol Protocol httpWhoisProtocol) { - return new ProbingStepWeb<>(httpWhoisProtocol); + @WebWhoisProtocol + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, + WebWhoisToken webWhoisToken, + @WebWhoisProtocol Bootstrap bootstrap) { + + return new ProbingSequence.Builder() + .addToken(webWhoisToken) + .setBootstrap(bootstrap) + .addStep(probingStepBuilder) + .build(); } + + /** {@link Provides} only step used in WebWhois sequence. */ @Provides - @HttpsWhoisProtocol - static ProbingStep provideHttpsWhoisProbingStep( - @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { - return new ProbingStepWeb<>(httpsWhoisProtocol); + @WebWhoisProtocol + static ProbingStep.Builder provideWebWhoisStepBuilder( + @HttpWhoisProtocol Protocol httpWhoisProtocol, + HttpRequestMessage messageTemplate, + Duration duration) { + + return ProbingStep.builder() + .setProtocol(httpWhoisProtocol) + .setMessageTemplate(messageTemplate) + .setDuration(duration); } - + /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides @HttpWhoisProtocol @@ -80,28 +104,14 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpProtocolForSet( - @HttpWhoisProtocol int httpWhoisPort, - @HttpWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTP_PROTOCOL_NAME) + .setPort(httpWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } - + /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ @Singleton @Provides @HttpsWhoisProtocol @@ -109,40 +119,28 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpsProtocolForSet( - @HttpsWhoisProtocol int httpsWhoisPort, - @HttpsWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTPS_PROTOCOL_NAME) + .setPort(httpsWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } + /** {@link Provides} the prefix where we probe: "prefix.tld". */ @Provides - @WebWhoisProtocol - String provideHttpWhoisHost() { - return "app"; + @Named("Web-WHOIS-Prefix") + String provideWhoisPrefix() { + return DOMAIN_PREFIX; } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -151,13 +149,14 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -167,33 +166,57 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } + @Provides + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); + } + + @Provides + static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { + return new HttpObjectAggregator(maxContentLength); + } + + /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + @Provides + @HttpsWhoisProtocol + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); + } + /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + @Singleton @Provides @WebWhoisProtocol - static MessageHandler provideMessageHandler() { - return new WebWhoisMessageHandler(); + static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + return new Bootstrap() + .group(eventLoopGroup) + .channel(NioSocketChannel.class); } @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); + @WebWhoisProtocol + int provideMaximumMessageLengthBytes() { + return maximumMessageLengthBytes; } + /** {@link Provides} the list of top level domains to be probed */ + @Singleton @Provides - static HttpObjectAggregator provideHttpObjectAggregator() { - return new HttpObjectAggregator(1048576); + @WebWhoisProtocol + ImmutableList provideTopLevelDomains() { + return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); } @Provides - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index 776a231d6dd..be3d725c833 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,10 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when the action - * performed failed due to an issue in the connection with the server. + * Base exception class for all instances when the status of the action performed is ERROR. */ -public class ConnectionException extends UndeterminedStateException { +public class ConnectionException extends Exception { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index c3622e1b810..2e155b40afd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,10 +14,11 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.ChannelFuture; @@ -26,17 +27,18 @@ import io.netty.channel.SimpleChannelInboundHandler; /** - * Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, - * as it should only be passed in messages that implement the {@link InboundMessageType} interface. + *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link - * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. - * Second, it stores the {@link OutboundMessageType} passed down the pipeline, so that subclasses - * can use that information for their own processes. Lastly, with any exception thrown, the - * connection is closed, and the ProbingAction governing this channel is informed of the error. - * Subclasses specify further work to be done for specific kinds of channel pipelines. + *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed + * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} + * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * + *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -48,33 +50,41 @@ public enum ResponseType {SUCCESS, FAILURE, ERROR} /** Status of response for current {@link ActionHandler} instance */ private static ResponseType status; + /** {@link ChannelPromise} that informs {@link google.registry.monitoring.blackbox.ProbingAction} if response has been received. */ protected ChannelPromise finished; - /** - * Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized - * {@link ChannelPromise} - */ + /** Returns initialized {@link ChannelPromise} to {@link google.registry.monitoring.blackbox.ProbingAction}.*/ public ChannelFuture getFuture() { return finished; } - /** Initializes new {@link ChannelPromise} */ + /** Initializes the same {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { // Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } + /** Initializes the same {@link ChannelPromise} in case current channel is reused (usually for EPP).*/ + public void resetFuture() { + finished = finished.channel().newPromise(); + } + + /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { - //simply marks finished as success + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { + status = ResponseType.SUCCESS; - finished.setSuccess(); + + if (!finished.isSuccess()) { + finished.setSuccess(); + } } /** - * Logs the channel and pipeline that caused error, closes channel, then informs {@link - * ProbingAction} listeners of error + * Logs the channel and pipeline that caused error, closes channel, then informs + * {@link google.registry.monitoring.blackbox.ProbingAction} listeners of error. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { @@ -83,27 +93,62 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", ctx.channel().toString(), ctx.channel().pipeline().toString())); - - if (ResponseException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + if (cause instanceof ResponseException) { + //On ResponseException, we know the response is a failure. As a result, + //we set the status to FAILURE, then inform the MetricsHandler of this status = ResponseType.FAILURE; + + //Since it wasn't a success, we still want to log to see what caused the FAILURE logger.atInfo().log(cause.getMessage()); + + //As always, inform the ProbingStep that we successfully completed this action finished.setSuccess(); - } else if (ServerSideException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + + } else if (cause instanceof ConnectionException) { + //On ConnectionException, we know the response type is an error. As a result, + //we set the status to ERROR, then inform the MetricsHandler of this status = ResponseType.ERROR; + + //Since it wasn't a success, we still log what caused the ERROR logger.atInfo().log(cause.getMessage()); finished.setSuccess(); - } else if (InternalException.class.isInstance(cause)){ + + //As this was an ERROR in the connection, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + } else if (cause instanceof InternalException){ + //For an internal error, metrics should not be collected, so we log what caused this, and + //inform the ProbingStep the Prober had an internal error on this action logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); + + + //As this was an internal error, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } else { - finished.setFailure(cause); + //In the case of any other kind of error, we assume it is some type of connection ERROR, + //so we treat it as such: + + status = ResponseType.ERROR; + + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - //due to failure, close channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + + } + + /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ + @VisibleForTesting + ResponseType getStatus() { + return status; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index ac844ac99df..919006592ea 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -89,8 +90,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); - Protocol protocol = action.protocol(); + Protocol protocol = channel.attr(PROTOCOL_KEY).get(); + String host = channel.attr(REMOTE_ADDRESS_KEY).get(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -103,7 +104,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), action.host(), protocol.port()); + .newHandler(channel.alloc(), host, protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 0acf223eb9e..58c395ad86e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -17,37 +17,36 @@ import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; /** - * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection + * in case of reuse for redirection. */ -public class WebWhoisMessageHandler extends MessageHandler { - - private HttpRequestMessage request; +public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method*/ + /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - request = (HttpRequestMessage) msg; + HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; - InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); + HttpResponseMessage response = new HttpResponseMessage(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b06938d80a1..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,19 +19,30 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); @@ -39,18 +50,29 @@ public HttpRequestMessage setUri(String path) { } /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; - ByteBuf buf = request.content(); + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; - request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + } else { + throw new IllegalArgumentException(); + } + } - return finalRequest; + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 283b14440ac..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -34,17 +34,9 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 2d5df10f8c1..be6c872cc3e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,16 @@ package google.registry.monitoring.blackbox.messages; +import google.registry.monitoring.blackbox.exceptions.InternalException; + /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType {} +public interface OutboundMessageType { + + /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + public OutboundMessageType modifyMessage(String... args) throws InternalException; + + /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + public String name(); +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index b10c45dae8a..dd1882b5686 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,58 +14,41 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.ProbingSequence; -import google.registry.monitoring.blackbox.ProbingStep; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} in a single loop of a - * {@link ProbingSequence}. + * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} + * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes on channel that remains unchanged within a - * loop of the sequence.

+ * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop * in the sequence.

*/ public abstract class Token { - /** - * {@link Channel} that always starts out as null. Once a persistent connection is made (such as - * EPP), that channel is stored in the token and passed on to later steps in the sequence until a - * new loop begins. - */ + /** {@link Channel} that always starts out as null. */ protected Channel channel; - /** - * Obtains next {@link Token} for next loop in sequence. - */ + /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); - /** - * String corresponding to host that is relevant for loop in sequence. - */ - public abstract String host(); + /** String corresponding to host that is relevant for loop in sequence. */ + public abstract String getHost(); - /** - * Modifies the {@link OutboundMessageType} in the manner necessary for each loop - */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) - throws UndeterminedStateException; + /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; - /** - * Set method for {@code channel} - */ + /** Set method for {@code channel} */ public void setChannel(Channel channel) { this.channel = channel; } - /** - * Get method for {@code channel}. - */ + /** Get method for {@code channel}. */ public Channel channel() { return this.channel; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 3ff852f3556..2847e5ce0eb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,67 +16,59 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; +import java.util.List; import javax.inject.Inject; +import javax.inject.Named; /** * {@link Token} subtype designed for WebWhois sequence. * *

Between loops of a WebWhois sequence the only thing changing is the tld we - * are probing. As a result, we maintain the list of {@code topLevelDomains} and on each call to - * next, have our index looking at the next {@code topLevelDomain}.

+ * are probing. As a result, we maintain the list of {@code topLevelDomains} and + * on each call to next, have our index looking at the next {@code topLevelDomain}.

*/ public class WebWhoisToken extends Token { - /** - * For each top level domain (tld), we probe "prefix.tld". - */ - private static final String PREFIX = "whois.nic."; + /** For each top level domain (tld), we probe "prefix.tld". */ + private final String prefix; - /** - * {@link ImmutableList} of all top level domains to be probed. - */ - private final Iterator topLevelDomainsIterator; + /** {@link ImmutableList} of all top level domains to be probed. */ + private final ImmutableList topLevelDomains; - /** - * Current index of {@code topLevelDomains} that represents tld we are probing. - */ - private String currentDomain; + /** Current index of {@code topLevelDomains} that represents tld we are probing. */ + private int domainsIndex; @Inject - public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken( + @Named("Web-WHOIS-Prefix") String prefix, + @WebWhoisProtocol ImmutableList topLevelDomains) { - topLevelDomainsIterator = topLevelDomains.iterator(); - currentDomain = topLevelDomainsIterator.next(); + domainsIndex = 0; + this.prefix = prefix; + this.topLevelDomains = topLevelDomains; } - /** - * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. - */ + /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + domainsIndex += 1; + domainsIndex %= topLevelDomains.size(); return this; } - /** - * Modifies message to reflect the new host coming from the new top level domain. - */ + /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) - throws UndeterminedStateException { - return original.modifyMessage(host()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { + return original.modifyMessage(getHost()); } - /** - * Returns host as the concatenation of fixed {@code prefix} and current value of {@code - * topLevelDomains}. - */ + /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String host() { - return PREFIX + currentDomain; + public String getHost() { + return prefix + topLevelDomains.get(domainsIndex); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Mon, 29 Jul 2019 12:04:58 -0400 Subject: [PATCH 178/337] Minor Style Fixes --- .../monitoring/blackbox/ProbingAction.java | 85 ++++++++++--------- .../monitoring/blackbox/ProbingStep.java | 8 +- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..3f6a962b12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -89,11 +90,47 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** The {@link SocketAddress} instance that specifies remote address of connection */ + @Nullable public abstract SocketAddress address(); /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ public abstract Optional bootstrap(); + + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> actionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** * The method that performs the work of the actual action. * @@ -130,41 +167,13 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } @@ -224,7 +233,7 @@ public abstract static class Builder { abstract Channel channel(); - abstract Optional address(); + abstract SocketAddress address(); abstract Optional bootstrap(); @@ -233,7 +242,7 @@ public abstract static class Builder { abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) + if (address() == null) //If no address has been supplied, we set it based on the host and port setAddress(new InetSocketAddress(host(), protocol().port())); @@ -259,7 +268,7 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap().get().connect(address()); setChannel(connectionFuture.channel()); setConnectionFuture(connectionFuture); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index d54acef325a..47c89c72c11 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -21,7 +21,9 @@ import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import java.net.SocketAddress; import java.util.function.Consumer; +import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -48,6 +50,7 @@ public abstract class ProbingStep implements Consumer { abstract Protocol protocol(); abstract OutboundMessageType messageTemplate(); abstract Bootstrap bootstrap(); + @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -60,6 +63,8 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); + public abstract Builder setAddress(SocketAddress address); + public abstract ProbingStep build(); } @@ -87,7 +92,8 @@ private ProbingAction generateAction(Token token) throws InternalException { .setProtocol(protocol()) .setOutboundMessage(message) .setHost(token.getHost()) - .setBootstrap(bootstrap()); + .setBootstrap(bootstrap()) + .setAddress(address()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); From 2e7bce2fed3b8dcba6cba1ff7bd30b08bd00e0c4 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:05:59 -0400 Subject: [PATCH 179/337] Updated build.gradle file --- prober/build.gradle | 3 - .../blackbox/ProbingSequenceStepTest.java | 219 ----------------- .../blackbox/ProbingSequenceTest.java | 96 -------- .../monitoring/blackbox/ProbingStepTest.java | 223 +++++++++--------- 4 files changed, 110 insertions(+), 431 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java diff --git a/prober/build.gradle b/prober/build.gradle index 993da44655d..181188c5cee 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,7 +16,6 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - dependencies { def deps = rootProject.dependencyMap @@ -45,7 +44,6 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -55,4 +53,3 @@ dependencies { testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java deleted file mode 100644 index 7a713017072..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.TestUtils.TestStep; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.handlers.ConversionHandler; -import google.registry.monitoring.blackbox.handlers.NettyRule; -import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; -import org.junit.Rule; -import org.junit.Test; - -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { - - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ - private ProbingSequence testSequence; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); - dummyStep = new DummyStep(testProtocol, eventLoopGroup); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(false) - .build(); - } - - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(true) - .build(); - } - - /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ - private void setupSequence() { - testSequence = new ProbingSequence.Builder() - .eventLoopGroup(eventLoopGroup) - .setClass(LocalChannel.class) - .addStep(firstStep) - .makeFirstRepeated() - .addStep(dummyStep) - .build(); - } - - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.nextStep()).isNull(); - - //we expect that this exception be thrown - assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); - - } - - @Test - public void testWithSequence_NewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupSequence(); - setupNewChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupSequence(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 5c4452df7b3..2b0559514a2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,101 +1,5 @@ -// Copyright 2019 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.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doCallRealMethod; - -import google.registry.monitoring.blackbox.tokens.Token; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) public class ProbingSequenceTest { - - private ProbingStep setupMock() { - ProbingStep mock = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(mock).nextStep(); - return mock; - } - - private static class Wrapper { - - T data; - - public Wrapper(T data) { - this.data = data; - } - } - - @Test - public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(firstStep) - .addStep(secondStep) - .addStep(thirdStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(thirdStep); - assertThat(thirdStep.nextStep()).isEqualTo(firstStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - - @Test - public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(thirdStep) - .addStep(secondStep) - .markFirstRepeated() - .addStep(firstStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(firstStep); - assertThat(thirdStep.nextStep()).isEqualTo(secondStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 307d19221dd..090753014e4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,203 +11,200 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.TestUtils.dummyStep; +import static google.registry.monitoring.blackbox.TestUtils.testStep; +import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; -import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; -import org.mockito.Mockito; - -/** - * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific - * implementations - */ -public class ProbingStepTest { - - /** - * Basic Constants necessary for tests - */ - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final int PROTOCOL_PORT = 0; - private static final String TEST_MESSAGE = "TEST_MESSAGE"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - private static final LocalAddress ADDRESS = new LocalAddress(ADDRESS_NAME); + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - /** - * Used for testing how well probing step can create connection to blackbox server - */ + /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** - * The two main handlers we need in any test pipeline used that connects to {@link NettyRule's - * server} - **/ + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** - * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} - * is called, it just marks the supplied future as succeeded, returning the requisite token. - */ - private ProbingStep dummyStep() { - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(dummyStep).nextStep(); - return dummyStep; + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); } + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } - @Test - public void testNewChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } - // Sets up Protocol for when we create a new channel. - Protocol testProtocol = Protocol.builder() + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); + dummyStep = dummyStep(eventLoopGroup); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); + } - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) .build(); + } - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); + //there should be no next step + assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); - //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(ADDRESS); + } + + @Test + public void testNewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //checks that we have appropriately sent the write message to server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - verify(dummyStep, times(1)).accept(any(Token.class)); + assertThat(future.get()).isEqualTo(testToken); + } - @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - - // Sets up Protocol for when a channel already exists. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) - .build(); - - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) - .build(); - - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); - - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - - //Assures that the channel has a succeeded connectionFuture. - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, ""); + //setup + setupExistingProtocol(); + setupSteps(); + setupChannel(); + setupExistingChannelToken(); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message through the EmbeddedChannel - // pipeline + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); - Object msg = channel.readOutbound(); - - while (msg == null) { - msg = channel.readOutbound(); - } //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf) channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked - // as a success - verify(dummyStep, times(1)).accept(any(Token.class)); + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); } } From b426749e324acb62f69f5b36eca2d94304aab694 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 180/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From 6189dd2a189dcaa2312c221cca21b097a4b6d7a1 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:54:13 -0400 Subject: [PATCH 181/337] Updated WebWhois tests. --- .../blackbox/ProbingActionTest.java | 56 +++--- .../blackbox/ProbingSequenceTest.java | 183 ++++++++++++++++++ .../monitoring/blackbox/ProbingStepTest.java | 3 +- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 93 +++++++-- .../monitoring/blackbox/TokenTest.java | 13 +- .../blackbox/handlers/ConversionHandler.java | 2 +- .../blackbox/handlers/NettyRule.java | 12 +- .../handlers/SslClientInitializerTest.java | 46 ++--- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 158 ++++++++------- 11 files changed, 421 insertions(+), 157 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index cbcf2fc82b0..162044c2036 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -83,31 +84,31 @@ public class ProbingActionTest { /** Sets up a {@link Protocol} corresponding to when a new connection is created */ private void setupNewChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(false) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) .build(); } /** Sets up a {@link Protocol} corresponding to when a new connection exists */ private void setupExistingChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(true) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(true) .build(); } - /** Sets up a {@link NewChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ private void setupNewChannelAction() { - newChannelAction = NewChannelAction.builder() - .bootstrap(bootstrap) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") - .address(address) + newChannelAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") + .setAddress(address) .build(); } @@ -115,25 +116,25 @@ private void setupChannel() { channel = new EmbeddedChannel(); } - /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ExistingChannelAction.builder() - .channel(channel) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") + existingChannelAction = ProbingAction.builder() + .setChannel(channel) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") .build(); } @Test - public void testBehavior_existingChannel() { + public void testBehavior_existingChannel() throws InternalException { //setup setupChannel(); setupExistingChannelProtocol(); - setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); + setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -147,6 +148,7 @@ public void testBehavior_existingChannel() { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -156,9 +158,9 @@ public void testBehavior_existingChannel() { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - setupNewChannelAction(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + setupNewChannelAction(); ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2b0559514a2..681a5346d55 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,5 +1,188 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; + +import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; +import java.net.SocketAddress; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) public class ProbingSequenceTest { + private final static String TEST_HOST = "TEST_HOST"; + + + private Bootstrap dummyBootstrap = new Bootstrap(); + private Token testToken = new ProbingSequenceTestToken(); + + /** + * Custom {@link ProbingStep} subclass that acts as a mock + * step, so we can test how well {@link ProbingSequence} builds + * a linked list of {@link ProbingStep}s from their {@link Builder}s. + */ + private static class TestStep extends ProbingStep { + private Bootstrap bootstrap; + private String marker; + + /** We implement all abstract methods to simply return null, as we have no use for them here. */ + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + SocketAddress address() { + return null; + } + + /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + /** + * Builder for {@link TestStep}, that extends {@link ProbingStep.Builder} so that these can be + * input into the {@link ProbingSequence.Builder}. + */ + public static class Builder extends ProbingStep.Builder { + /** We test to see if we accurately add the right bootstrap to all {@link ProbingStep}s/ */ + private Bootstrap bootstrap; + + /** We also mark each step in order to ensure that when running, they are arranged in the right order. */ + private String marker; + + @Override + public ProbingStep.Builder setDuration(Duration value) { + return this; + } + + @Override + public ProbingStep.Builder setProtocol(Protocol value) { + return this; + } + + @Override + public ProbingStep.Builder setMessageTemplate(OutboundMessageType value) { + return null; + } + + @Override + public ProbingStep.Builder setAddress(SocketAddress address) { + return null; + } + + @Override + public ProbingStep.Builder setBootstrap(Bootstrap value) { + bootstrap = value; + return this; + } + + public ProbingStep.Builder addMarker(String value) { + marker = value; + return this; + } + + @Override + public ProbingStep build() { + return new TestStep(bootstrap, marker); + } + } + private TestStep(Bootstrap bootstrap, String marker) { + this.bootstrap = bootstrap; + this.marker = marker; + } + + /** + * On a call to accept, we modify the token to reflect what the current step is, so we can get + * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated + * in order. + */ + @Override + public void accept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + if (!isLastStep) { + nextStep().accept(token); + } else { + ((TestStep)nextStep()).specialAccept(token); + } + } + + /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ + public void specialAccept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + return; + } + } + + @Test + public void testSequenceBasicConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("firstsecondthirdfirst"); + } + + @Test + public void testSequenceAdvancedConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(thirdStepBuilder) + .addStep(secondStepBuilder) + .markFirstRepeated() + .addStep(firstStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("thirdsecondfirstsecond"); + } + @Test + public void testSequenceConstruction_Failure() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + assertThrows(AssertionError.class, () -> { + ProbingSequence sequence = new ProbingSequence.Builder() + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .setBootstrap(dummyBootstrap) + .build(); + }); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 090753014e4..ee38e7cdf74 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -21,7 +21,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; @@ -47,7 +46,7 @@ import org.junit.Test; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { +public class ProbingStepTest { /** Basic Constants necessary for tests */ private final String ADDRESS_NAME = "TEST_ADDRESS"; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 06b19ea3607..337d755e971 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -93,11 +93,11 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 8d1722c9625..161304c1f04 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,9 +17,11 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -37,6 +39,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; +import java.net.Socket; +import java.net.SocketAddress; +import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -141,26 +146,67 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } + + @Override + public OutboundMessageType modifyMessage(String... args) throws InternalException { + message = args[0]; + return this; + } + + @Override + public String name() { + return "Test Message of: " + this.toString(); + } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static class TestStep extends ProbingStep { + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .setAddress(address) + .build(); - public TestStep(Protocol protocol, String testMessage, LocalAddress address) { - super(protocol, new DuplexMessageTest(testMessage)); - this.address = address; - this.duration = Duration.ZERO; - } + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { - super(protocol, new DuplexMessageTest()); - future = new DefaultPromise(eventLoopGroup.next()) {}; - duration = Duration.ZERO; + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; + } + + @Nullable + @Override + SocketAddress address() { + return null; } @Override @@ -170,11 +216,16 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } + + @Override + public String toString() { + return "Dummy Step"; + } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - private String host; + protected String host; protected TestToken(String host) { this.host = host; @@ -221,6 +272,22 @@ public Channel channel() { } } + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..67963805733 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,10 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; @@ -34,20 +35,20 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..a8506a996a9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -37,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b6b5e8fbe0c..b38c1911940 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; @@ -89,7 +90,8 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - ProbingAction probingAction, + Protocol protocol, + String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -109,7 +111,9 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROBING_ACTION_KEY, probingAction); + .attr(PROTOCOL_KEY, protocol) + .attr(REMOTE_ADDRESS_KEY, host); + channel = b.connect(localAddress).syncUninterruptibly().channel(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 469c62a8f75..83c8e132f07 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,17 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ExistingChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; @@ -45,7 +46,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; -import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,8 +67,6 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); - /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -93,15 +91,12 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .persistentConnection(false) - .build(); - - private ProbingAction probingAction; + private final static Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -113,23 +108,13 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } - private void setupProbingAction(Channel channel) { - probingAction = ExistingChannelAction.builder() - .delay(Duration.ZERO) - .host(SSL_HOST) - .channel(channel) - .outboundMessage(DEFAULT_MESSAGE) - .protocol(PROTOCOL) - .build(); - } - @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - setupProbingAction(channel); - channel.attr(PROBING_ACTION_KEY).set(probingAction); + channel.attr(PROTOCOL_KEY).set(PROTOCOL); + channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -160,8 +145,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -189,8 +173,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -219,8 +202,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 518bb9ba686..e170fad8b8c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox.handlers; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 71d8d66b6c0..00318ccd912 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,17 +15,17 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; @@ -37,9 +37,7 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; @@ -66,6 +64,14 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); + private static final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of()) + .setName("test_protocol") + .setPersistentConnection(false) + .setPort(HTTPS_PORT) + .build(); + private LocalAddress address; private EmbeddedChannel channel; @@ -76,30 +82,38 @@ public class WebWhoisActionHandlerTest { private void generateLocalAddress() { address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); } + /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { + private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of(actionHandlerProvider)) - .persistentConnection(false) + .setName(name) + .setPort(port) + .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) + .setPersistentConnection(persistentConnection) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); + private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { + actionHandler = new WebWhoisActionHandler( + bootstrap, + STANDARD_PROTOCOL, + STANDARD_PROTOCOL, + messageTemplate, + 80, + 443 + ); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); setupProbingActionBasic( protocol, outboundMessage, makeBootstrap(new NioEventLoopGroup(1))); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -109,24 +123,25 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { } /**Sets up probingAction for when testing redirection */ private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(TARGET_HOST) - .address(DEFAULT_ADDRESS) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(TARGET_HOST) + .setAddress(DEFAULT_ADDRESS) + .setChannel(channel) .build(); } private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(host) - .address(address) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(host) + .setAddress(address) .build(); } @@ -137,10 +152,13 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, true); generateLocalAddress(); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); @@ -150,7 +168,7 @@ public void testBasic_responseOk() throws Exception { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -166,9 +184,10 @@ public void testBasic_responseOk() throws Exception { @Test public void testBasic_responseFailure() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseBad", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseBad", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -179,8 +198,7 @@ public void testBasic_responseFailure() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage - .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -197,9 +215,10 @@ public void testBasic_responseFailure() { @Test public void testBasic_responseError() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseError", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseError", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -211,7 +230,7 @@ public void testBasic_responseError() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -222,26 +241,30 @@ public void testBasic_responseError() { assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_redirectCloseChannel() { //setup - HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", 0); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", 0, true); generateLocalAddress(); - setupChannel(initialProtocol, outboundMessage); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -257,12 +280,15 @@ public void testBasic_redirectCloseChannel() { @Test public void testBasic_redirectHost() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); generateLocalAddress(); setupChannel(initialProtocol, msg); - HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); //store future @@ -272,27 +298,24 @@ public void testBasic_redirectHost() { channel.writeInbound(originalResponse); - ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - //gets changed protocol - Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); - assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); } @Test - public void testAdvanced_responseOk() { + public void testAdvanced_responseOk() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); //stores future ChannelFuture future = probingAction.call(); @@ -302,15 +325,16 @@ public void testAdvanced_responseOk() { } @Test - public void testAdvanced_responseFailure() { + public void testAdvanced_responseFailure() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); //stores future ChannelFuture future = probingAction.call(); From 138f6810cc058189f4fc74b2bbf771a6c08ede71 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 182/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- prober/.gitignore | 1 + .../registry/monitoring/blackbox/Prober.java | 9 +- .../monitoring/blackbox/ProberModule.java | 15 ++- .../monitoring/blackbox/ProbingAction.java | 96 +++++++-------- .../monitoring/blackbox/ProbingSequence.java | 24 +--- .../monitoring/blackbox/ProbingStep.java | 55 ++++++--- .../monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 49 ++++---- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 30 ----- .../exceptions/ResponseException.java | 29 ----- .../UndeterminedStateException.java | 5 +- .../blackbox/handlers/ActionHandler.java | 102 ++++------------ .../handlers/WebWhoisActionHandler.java | 51 ++++---- .../blackbox/messages/HttpRequestMessage.java | 4 +- .../messages/HttpResponseMessage.java | 6 +- .../messages/OutboundMessageType.java | 7 +- .../monitoring/blackbox/tokens/Token.java | 20 +-- .../blackbox/tokens/WebWhoisToken.java | 32 +++-- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../blackbox/ProbingActionTest.java | 9 +- .../blackbox/ProbingSequenceTest.java | 114 +++--------------- .../monitoring/blackbox/ProbingStepTest.java | 4 +- .../monitoring/blackbox/TestUtils.java | 21 +--- .../monitoring/blackbox/TokenTest.java | 8 +- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 103 +++++----------- 31 files changed, 283 insertions(+), 528 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/.gitignore b/prober/.gitignore index 89f9ac04aac..77b1e2de2de 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1 +1,2 @@ out/ +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..307afd34d81 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +29,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 0daaf16ded4..1db97d1b581 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,14 +14,18 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.Set; import javax.inject.Singleton; import org.joda.time.Duration; @@ -33,7 +37,7 @@ public class ProberModule { /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = new Duration(4000L); + private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @@ -42,6 +46,12 @@ EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + @Provides + @Singleton + Class provideChannelClass() { + return NioSocketChannel.class; + } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides @Singleton @@ -51,6 +61,7 @@ Duration provideDuration() { /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides + @Singleton static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; @@ -66,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); + Set provideAllSequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 3f6a962b12d..67494dd5f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,25 +14,29 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -65,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -80,31 +87,18 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - @Nullable - public abstract SocketAddress address(); - - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { // Write appropriate outboundMessage to pipeline ChannelFuture channelFuture = actionHandler.getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> actionHandler.resetFuture(), - //inform ProbingStep of the status of our action future -> { if (future.isSuccess()) @@ -141,7 +135,7 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -154,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -180,19 +174,24 @@ public ChannelFuture performAction() throws InternalException { /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -210,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -221,40 +226,30 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract SocketAddress address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (address() == null) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + System.out.println("test"); + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -268,14 +263,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -293,7 +285,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2dbf48256f9..91c4165c068 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -49,32 +49,18 @@ public static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; private ProbingStep firstRepeatedStep; - private Bootstrap bootstrap; - private Token startToken; - /** - * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. - * - *

Must be called before adding {@link ProbingStep.Builder}s.

- */ - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } + private Token startToken; - /** Adds start token that activate {@link ProbingSequence}. */ - public Builder addToken(Token token) { - startToken = token; - return this; + public Builder(Token startToken) { + this.startToken = startToken; } /** - * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, * built, and pointed to by the previous {@link ProbingStep} added. */ - public Builder addStep(ProbingStep.Builder stepBuilder) { - assert (bootstrap != null); - ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + public Builder addStep(ProbingStep step) { if (currentStep == null) firstStep = step; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 47c89c72c11..ca980100067 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import java.net.SocketAddress; import java.util.function.Consumer; -import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -39,18 +37,23 @@ @AutoValue public abstract class ProbingStep implements Consumer { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ - private boolean isLastStep = false; + protected boolean isLastStep = false; private ProbingStep nextStep; + /** Time delay duration between actions. */ abstract Duration duration(); + + /** {@link Protocol} type for this step. */ abstract Protocol protocol(); + + /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ abstract OutboundMessageType messageTemplate(); + + /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ abstract Bootstrap bootstrap(); - @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -63,8 +66,6 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); - public abstract Builder setAddress(SocketAddress address); - public abstract ProbingStep build(); } @@ -85,18 +86,18 @@ ProbingStep nextStep() { } /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws InternalException { + private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) .setProtocol(protocol()) .setOutboundMessage(message) - .setHost(token.getHost()) - .setBootstrap(bootstrap()) - .setAddress(address()); + .setHost(token.host()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); + else + probingActionBuilder.setBootstrap(bootstrap()); return probingActionBuilder.build(); } @@ -107,44 +108,58 @@ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } + /** + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. + * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

+ */ @Override public void accept(Token token) { ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - //call the created action ChannelFuture future; - try { + //call the generated action future = currentAction.call(); - - } catch(InternalException e) { + } catch(UndeterminedStateException e) { + //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); + + //Move on to next step in ProbingSequence nextStep.accept(generateNextToken(token)); return; } - //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - //If the next step maintains the connection, pass on the channel from this + } else { + //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index ef52cb9c4bf..624f08fd4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -29,7 +29,7 @@ public abstract class Protocol { /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - abstract String name(); + public abstract String name(); public abstract int port(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dcc9635beaa..c5e41fea38b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,6 +18,7 @@ import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,6 +27,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; @@ -44,11 +46,10 @@ @Module public class WebWhoisModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - private static final String DOMAIN_PREFIX = "whois.nic."; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; + private static final String HTTP_PROTOCOL_NAME = "http"; + private static final String HTTPS_PROTOCOL_NAME = "https"; /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; @@ -68,16 +69,14 @@ public class WebWhoisModule { /** {@link Provides} standard WebWhois sequence. */ @Provides - @WebWhoisProtocol + @Singleton + @IntoSet ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, - WebWhoisToken webWhoisToken, - @WebWhoisProtocol Bootstrap bootstrap) { + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { - return new ProbingSequence.Builder() - .addToken(webWhoisToken) - .setBootstrap(bootstrap) - .addStep(probingStepBuilder) + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) .build(); } @@ -85,15 +84,18 @@ ProbingSequence provideWebWhoisSequence( /** {@link Provides} only step used in WebWhois sequence. */ @Provides @WebWhoisProtocol - static ProbingStep.Builder provideWebWhoisStepBuilder( + static ProbingStep provideWebWhoisStep( @HttpWhoisProtocol Protocol httpWhoisProtocol, + @WebWhoisProtocol Bootstrap bootstrap, HttpRequestMessage messageTemplate, Duration duration) { return ProbingStep.builder() .setProtocol(httpWhoisProtocol) + .setBootstrap(bootstrap) .setMessageTemplate(messageTemplate) - .setDuration(duration); + .setDuration(duration) + .build(); } /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @@ -126,13 +128,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** {@link Provides} the prefix where we probe: "prefix.tld". */ - @Provides - @Named("Web-WHOIS-Prefix") - String provideWhoisPrefix() { - return DOMAIN_PREFIX; - } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @@ -187,10 +182,12 @@ static SslClientInitializer provideSslClientInitializer(SslPro @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + static Bootstrap provideBootstrap( + EventLoopGroup eventLoopGroup, + Class channelClass){ return new Bootstrap() .group(eventLoopGroup) - .channel(NioSocketChannel.class); + .channel(channelClass); } @Provides @@ -210,13 +207,13 @@ ImmutableList provideTopLevelDomains() { @Provides @HttpWhoisProtocol int provideHttpWhoisPort() { - return httpWhoIsPort; + return HTTP_WHOIS_PORT; } @Provides @HttpsWhoisProtocol int provideHttpsWhoisPort() { - return httpsWhoIsPort; + return HTTPS_WHOIS_PORT; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index be3d725c833..adb833ec629 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,9 +15,10 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is ERROR. + * Subclass of {@link UndeterminedStateException} that represents all instances when + * the action performed failed due to an issue in the connection with the server. */ -public class ConnectionException extends Exception { +public class ConnectionException extends UndeterminedStateException { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java index d7127717d52..c155d695c7f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java @@ -15,8 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails before we can determine - * the state of the result, meaning the status is recorded as ERROR. + * Base exception class for all instances when the action performed fails + * before we can determine the state of the result, meaning the status + * is recorded as ERROR. */ public class UndeterminedStateException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 2e155b40afd..247424243cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,17 +14,15 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; /** *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline @@ -33,7 +31,7 @@ * messages that implement the {@link InboundMessageType} interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

@@ -44,111 +42,59 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); - - } else if (cause instanceof InternalException){ - //For an internal error, metrics should not be collected, so we log what caused this, and - //inform the ProbingStep the Prober had an internal error on this action - logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - - //As this was an internal error, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } else { - //In the case of any other kind of error, we assume it is some type of connection ERROR, - //so we treat it as such: - - status = ResponseType.ERROR; + //On UndeterminedStateException, we know the response type is an error. - logger.atInfo().log(cause.getMessage()); - finished.setSuccess(); + //Since it wasn't a success, we still log what caused the ERROR + logger.atWarning().log(cause.getMessage()); + finished.setFailure(cause); + //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } - - /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ - @VisibleForTesting - ResponseType getStatus() { - return status; - } -} - +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 69d5b7f1603..1ec4e314813 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -22,13 +22,12 @@ import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -62,27 +61,17 @@ public class WebWhoisActionHandler extends ActionHandler { /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ private final HttpRequestMessage requestMessage; - /** Default port for http. */ - private int httpPort; - - /** default port for https. */ - private int httpsPort; - @Inject public WebWhoisActionHandler( @WebWhoisProtocol Bootstrap bootstrap, @HttpWhoisProtocol Protocol httpWhoisProtocol, @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage, - @HttpWhoisProtocol int httpPort, - @HttpsWhoisProtocol int httpsPort) { + HttpRequestMessage requestMessage) { this.bootstrap = bootstrap; this.httpWhoisProtocol = httpWhoisProtocol; this.httpsWhoisProtocol = httpsWhoisProtocol; this.requestMessage = requestMessage; - this.httpPort = httpPort; - this.httpsPort = httpsPort; } @@ -93,7 +82,7 @@ public WebWhoisActionHandler( */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -112,7 +101,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -123,12 +112,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; - if (newPort == httpPort) { + if (url.getProtocol().equals(httpWhoisProtocol.name())) { newProtocol = httpWhoisProtocol; - } else if (newPort == httpsPort) { + } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -143,34 +132,38 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) .setHost(newHost) .build(); - //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); - //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..b4c01d06a8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,12 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..f1b2d6ac6a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -25,11 +25,7 @@ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { - super(version, status); - } - - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index be6c872cc3e..6e3da3f69d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,7 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline @@ -22,8 +22,9 @@ public interface OutboundMessageType { /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - public OutboundMessageType modifyMessage(String... args) throws InternalException; + OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - public String name(); + @Override + String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dd1882b5686..dab5851e8d8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,16 +14,18 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.ProbingSequence; +import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} - * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} + * in a single loop of a {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * in a {@link ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -31,17 +33,21 @@ */ public abstract class Token { - /** {@link Channel} that always starts out as null. */ + /** + * {@link Channel} that always starts out as null. Once a persistent connection + * is made (such as EPP), that channel is stored in the token and passed on to + * later steps in the sequence until a new loop begins. + */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String getHost(); + public abstract String host(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 2847e5ce0eb..bb06ee89db6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import javax.inject.Inject; import javax.inject.Named; @@ -33,42 +33,38 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final String prefix; + private final static String PREFIX = "whois.nic."; /** {@link ImmutableList} of all top level domains to be probed. */ - private final ImmutableList topLevelDomains; + private final Iterator topLevelDomainsIterator; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private int domainsIndex; + private String currentDomain; @Inject - public WebWhoisToken( - @Named("Web-WHOIS-Prefix") String prefix, - @WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { - domainsIndex = 0; - this.prefix = prefix; - this.topLevelDomains = topLevelDomains; + topLevelDomainsIterator = topLevelDomains.iterator(); + currentDomain = topLevelDomainsIterator.next(); } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - domainsIndex += 1; - domainsIndex %= topLevelDomains.size(); + currentDomain = topLevelDomainsIterator.next(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { - return original.modifyMessage(getHost()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + return original.modifyMessage(host()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String getHost() { - return prefix + topLevelDomains.get(domainsIndex); + public String host() { + return PREFIX + currentDomain; } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( { - ProbingSequence sequence = new ProbingSequence.Builder() - .addStep(firstStepBuilder) - .addStep(secondStepBuilder) - .addStep(thirdStepBuilder) - .addToken(testToken) - .setBootstrap(dummyBootstrap) - .build(); - }); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index ee38e7cdf74..7bba9d66782 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.TestUtils.dummyStep; import static google.registry.monitoring.blackbox.TestUtils.testStep; import static google.registry.testing.JUnitBackports.assertThrows; @@ -90,7 +91,7 @@ public class ProbingStepTest { /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ private void setupNewChannelToken() { - testToken = new NewChannelToken(""); + testToken = new NewChannelToken(ADDRESS_NAME); } /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ @@ -101,6 +102,7 @@ private void setupExistingChannelToken() { /** Sets up an embedded channel to contain the two handlers we created already */ private void setupChannel() { channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 161304c1f04..68bdd0bcef0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,7 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,8 +26,6 @@ import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpMessage; @@ -39,7 +37,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; -import java.net.Socket; import java.net.SocketAddress; import javax.annotation.Nullable; import javax.inject.Provider; @@ -148,15 +145,10 @@ public String toString() { } @Override - public OutboundMessageType modifyMessage(String... args) throws InternalException { + public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { message = args[0]; return this; } - - @Override - public String name() { - return "Test Message of: " + this.toString(); - } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ @@ -166,7 +158,6 @@ public static ProbingStep testStep(Protocol protocol, String testMessage, Bootst .setDuration(Duration.ZERO) .setMessageTemplate(new DuplexMessageTest(testMessage)) .setBootstrap(bootstrap) - .setAddress(address) .build(); } @@ -203,12 +194,6 @@ Bootstrap bootstrap() { return null; } - @Nullable - @Override - SocketAddress address() { - return null; - } - @Override public void accept(Token token) { future.setSuccess(token); @@ -241,7 +226,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String getHost() { + public String host() { return host; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index 67963805733..295bb809a13 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -17,12 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -37,7 +35,7 @@ public class TokenTest { private static String TEST_STARTER = "starter"; private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { @@ -49,7 +47,7 @@ public void testWebToken_MessageModificationSuccess() { try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index e170fad8b8c..3ecbdcc0d06 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -29,7 +29,7 @@ public class TestActionHandler extends ActionHandler { @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 00318ccd912..83d004d4555 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,17 +15,20 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; @@ -63,11 +66,9 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); private static final Protocol STANDARD_PROTOCOL = Protocol.builder() .setHandlerProviders(ImmutableList.of()) - .setName("test_protocol") + .setName("http") .setPersistentConnection(false) .setPort(HTTPS_PORT) .build(); @@ -79,8 +80,10 @@ public class WebWhoisActionHandlerTest { private ProbingAction probingAction; private Provider actionHandlerProvider; - private void generateLocalAddress() { - address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + private String generateLocalAddress(String addressString) { + String modifiedAddress = addressString + System.currentTimeMillis(); + address = new LocalAddress(modifiedAddress); + return modifiedAddress; } /** Creates default protocol with empty list of handlers and specified other inputs */ @@ -99,9 +102,7 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT bootstrap, STANDARD_PROTOCOL, STANDARD_PROTOCOL, - messageTemplate, - 80, - 443 + messageTemplate ); actionHandlerProvider = new TestProvider<>(actionHandler); } @@ -110,10 +111,8 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - setupProbingActionBasic( - protocol, - outboundMessage, - makeBootstrap(new NioEventLoopGroup(1))); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -122,26 +121,23 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } /**Sets up probingAction for when testing redirection */ - private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) .setHost(TARGET_HOST) - .setAddress(DEFAULT_ADDRESS) .setChannel(channel) .build(); } - private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) .setBootstrap(bootstrap) - .setHost(host) - .setAddress(address) + .setHost(addressString) .build(); } @@ -156,8 +152,6 @@ public void testBasic_responseOk() throws Exception { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseOk", 0, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); //stores future @@ -182,13 +176,12 @@ public void testBasic_responseOk() throws Exception { } @Test - public void testBasic_responseFailure() { + public void testBasic_responseFailure_badRequest() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseBad", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -210,16 +203,15 @@ public void testBasic_responseFailure() { assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testBasic_responseError() { + public void testBasic_responseFailure_badURL() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseError", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -239,9 +231,9 @@ public void testBasic_responseError() { //assesses that listener is triggered, and event is success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException); } @Test @@ -253,7 +245,6 @@ public void testBasic_redirectCloseChannel() { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("redirectHttp", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -278,44 +269,15 @@ public void testBasic_redirectCloseChannel() { } @Test - public void testBasic_redirectHost() { - //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); - HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); - - - //store future - ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); - - - channel.writeInbound(originalResponse); - - Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - } - - @Test - public void testAdvanced_responseOk() throws InternalException { + public void testAdvanced_responseOk() throws UndeterminedStateException { //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); @@ -325,22 +287,21 @@ public void testAdvanced_responseOk() throws InternalException { } @Test - public void testAdvanced_responseFailure() throws InternalException { + public void testAdvanced_responseFailure() throws UndeterminedStateException { //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); + String host = generateLocalAddress(TARGET_HOST); HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(bootstrap, msg); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + assertThrows(FailureException.class, future::syncUninterruptibly); } } From 72dd6cd2b86e2f7b50a9ba309b39ea48e103f7e6 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:48:33 -0400 Subject: [PATCH 183/337] SpotlessApply run to fix style issues --- prober/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index 77b1e2de2de..c86568e7672 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From 73c3e71c4f3ca1c473d17bebe3f09d4e7de12a2a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:28:40 -0400 Subject: [PATCH 184/337] Added license header and newline where appropriate. --- prober/build.gradle | 1 + .../monitoring/blackbox/ProbingAction.java | 1 - .../blackbox/handlers/ActionHandler.java | 2 +- .../monitoring/blackbox/ProbingSequenceTest.java | 14 ++++++++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 181188c5cee..478d33e1ef9 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -35,6 +35,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] + compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 67494dd5f78..a8740e21c20 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -240,7 +240,6 @@ public ProbingAction build() { InetAddress hostAddress = InetAddress.getByName(host()); address = new InetSocketAddress(hostAddress, protocol().port()); } catch (UnknownHostException e) { - System.out.println("test"); address = new LocalAddress(host()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 247424243cb..433604d6495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -97,4 +97,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } -} \ No newline at end of file +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2a8d5ebe233..8d9e45c6a66 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; From 20ca1a45c166f49d1580ea6a933bd6d4f09ca9a7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 185/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/ProbingStepTest.java | 1 - .../blackbox/TestServers/WebWhoisServer.java | 3 +- .../monitoring/blackbox/TestUtils.java | 35 +------------------ .../blackbox/handlers/ConversionHandler.java | 5 ++- .../blackbox/handlers/NettyRule.java | 4 ++- 5 files changed, 10 insertions(+), 38 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 7bba9d66782..73b104ae5dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -174,7 +174,6 @@ public void testNewChannel() throws Exception { //checks that when the future is successful, we pass down the requisite token assertThat(future.get()).isEqualTo(testToken); - } @Test diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 337d755e971..e7f125bb906 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; @@ -80,7 +81,7 @@ static class RedirectHandler extends ChannelDuplexHandler { /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 68bdd0bcef0..cc8e1512fe9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; @@ -28,17 +27,13 @@ import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpMethod;; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; import java.net.SocketAddress; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -272,33 +267,5 @@ public void addToHost(String suffix) { } } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index a8506a996a9..196141bb875 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b38c1911940..1d14cf131e6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -26,6 +26,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.ProbingActionTest; +import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; @@ -54,7 +56,7 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { From 379871b401b488061cae23b74a37ba5d755e2856 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 5 Aug 2019 16:16:36 -0400 Subject: [PATCH 186/337] Refactored ProbingAction to minimize number of unnecessary methods --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 4 +- .../monitoring/blackbox/ProbingAction.java | 160 ++++++++---------- .../monitoring/blackbox/ProbingStep.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 4 +- .../blackbox/handlers/ActionHandler.java | 2 +- .../handlers/WebWhoisActionHandler.java | 7 +- .../blackbox/messages/HttpRequestMessage.java | 5 +- .../blackbox/ProbingActionTest.java | 130 +++++++------- .../blackbox/ProbingSequenceTest.java | 25 ++- .../monitoring/blackbox/ProbingStepTest.java | 6 + .../monitoring/blackbox/TestUtils.java | 2 +- .../handlers/WebWhoisActionHandlerTest.java | 11 +- 13 files changed, 178 insertions(+), 183 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 307afd34d81..e12d1f0f522 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; import java.util.Set; @@ -29,7 +30,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); + Set sequences = proberComponent.sequences(); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 1db97d1b581..fb83b236b69 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -49,7 +49,7 @@ EventLoopGroup provideEventLoopGroup() { /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides @Singleton - Class provideChannelClass() { + Class provideChannelClazz() { return NioSocketChannel.class; } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @@ -77,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - Set provideAllSequences(); + Set sequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index a8740e21c20..25c3a1c17d6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -33,10 +33,8 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -69,6 +67,8 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -85,6 +85,7 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ @@ -94,108 +95,89 @@ public abstract class ProbingAction implements Callable { public abstract String host(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } - /** - * The method that performs the work of the actual action. + * Performs the work of the actual action * - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ *

First, checks if channel is active by setting a listener to perform the bulk of the work + * when the connection future is successful.

+ * + *

Once the connection is successful, we establish which of the handlers in the pipeline is + * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when + * we receive an expected response from the server.

+ * + *

Next, we set a timer set to a specified delay. After the delay has passed, we send the + * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, + * we inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - - //ChannelPromise that we use to inform ProbingStep when we are finished. - ChannelPromise finished = channel().newPromise(); - - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - - return finished; - } /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws UndeterminedStateException { + public ChannelFuture call() { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); + + //Ensures channel has been set up with connection future as an attribute + checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + //When connection is established call super.call and set returned listener to success channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { + (ChannelFuture connectionFuture) -> { + if (connectionFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); + ActionHandler actionHandler; + try { + actionHandler = channel().pipeline().get(ActionHandler.class); + } catch (ClassCastException e) { + //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); + } + + ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> { + if (future.isSuccess()) { + finished.setSuccess(); + } else { + finished.setFailure(future.cause()); + } + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) { + logger.atInfo() + .log("Closed stale channel. Moving on to next ProbingStep"); + } else { + logger.atWarning() + .log( + "Could not close channel. Stale connection still exists."); + } + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); } else { //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( + logger.atSevere().withCause(connectionFuture.cause()).log( "Cannot connect to relay channel for %s channel: %s.", protocol().name(), this.channel()); ChannelFuture unusedFuture = channel().close(); @@ -228,7 +210,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract Protocol protocol(); - abstract Optional channel(); + abstract Channel channel(); abstract String host(); @@ -243,11 +225,11 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { + if (channel() == null) { bootstrap.handler( new ChannelInitializer() { @Override diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index ca980100067..3df536a9478 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -135,7 +135,7 @@ public void accept(Token token) { try { //call the generated action future = currentAction.call(); - } catch(UndeterminedStateException e) { + } catch(Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index c5e41fea38b..2e640338511 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -184,10 +184,10 @@ static SslClientInitializer provideSslClientInitializer(SslPro @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClass){ + Class channelClazz){ return new Bootstrap() .group(eventLoopGroup) - .channel(channelClass); + .channel(channelClazz); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 433604d6495..ab628ed064f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -46,7 +46,7 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler testHandlerProvider = new TestProvider<>(testHandler); private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - private ProbingAction newChannelAction; - private ProbingAction existingChannelAction; - private EmbeddedChannel channel; - private Protocol protocol; - /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** Sets up a {@link Protocol} corresponding to when a new connection is created */ - private void setupNewChannelProtocol() { - protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - } - /** Sets up a {@link Protocol} corresponding to when a new connection exists */ - private void setupExistingChannelProtocol() { - protocol = Protocol.builder() + + + + @Test + public void testBehavior_existingChannel() throws UndeterminedStateException { + //setup + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up a Protocol corresponding to when a connection exists. + Protocol protocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) .build(); - } - - /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ - private void setupNewChannelAction() { - newChannelAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - } - - private void setupChannel() { - channel = new EmbeddedChannel(); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ - private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ProbingAction.builder() + // Sets up a ProbingAction that creates a channel using test specified attributes. + ProbingAction action = ProbingAction.builder() .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) .setHost("") .build(); - } - - @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { - //setup - setupChannel(); - setupExistingChannelProtocol(); - channel.pipeline().addLast(conversionHandler); - channel.pipeline().addLast(testHandler); - setupExistingChannelAction(channel); + //tests main function of ProbingAction + ChannelFuture future = action.call(); - ChannelFuture future = existingChannelAction.call(); - - //Ensures that we pass in the right message to the channel and haven't marked the future as success yet - Object msg = channel.readOutbound(); + //Obtains the outboundMessage passed through pipeline after delay + Object msg = null; + while (msg == null) { + msg = channel.readOutbound(); + } + //tests the passed message is exactly what we expect assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - assertThat(response).isEqualTo(TEST_MESSAGE); - assertThat(future.isSuccess()).isFalse(); + String request = ((ByteBuf) msg).toString(UTF_8); + assertThat(request).isEqualTo(TEST_MESSAGE); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -158,18 +122,40 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { @Test public void testSuccess_newChannel() throws Exception { //setup - setupNewChannelProtocol(); + + LocalAddress address = new LocalAddress(ADDRESS_NAME); + Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + // Sets up a Protocol corresponding to when a new connection is created. + Protocol protocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) + .build(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - setupNewChannelAction(); - ChannelFuture future = newChannelAction.call(); + + // Sets up a ProbingAction with existing channel using test specified attributes. + ProbingAction action = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) + .build(); + + //tests main function of ProbingAction + ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.sync(); + future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()); + assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 8d9e45c6a66..e5f91a300d6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -18,27 +18,44 @@ import static google.registry.testing.JUnitBackports.assertThrows; import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.TestUtils.TestToken; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import java.net.SocketAddress; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; @RunWith(JUnit4.class) public class ProbingSequenceTest { private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new ProbingSequenceTestToken(); + private Token testToken = new TestToken("") { + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + }; + private void setupMock(ProbingStep mock, ProbingStep nextStep) { + Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + } /** * Custom {@link ProbingStep} subclass that acts as a mock * step, so we can test how well {@link ProbingSequence} builds * a linked list of {@link ProbingStep}s from their {@link Builder}s. */ + private static class TestStep extends ProbingStep { private String marker; @@ -92,9 +109,9 @@ public void specialAccept(Token token) { @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 73b104ae5dc..256eeb0b29d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -45,6 +45,7 @@ import javax.inject.Provider; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ public class ProbingStepTest { @@ -191,6 +192,11 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); + Object msg = channel.readOutbound(); + + while (msg == null) { + msg = channel.readOutbound(); + } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index cc8e1512fe9..ef9926a7620 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -204,7 +204,7 @@ public String toString() { } /** Basic outline for {@link Token} instances to be used in tests */ - private static abstract class TestToken extends Token { + static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 83d004d4555..f6123045683 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -41,7 +41,6 @@ import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; import org.joda.time.Duration; @@ -155,7 +154,8 @@ public void testBasic_responseOk() throws Exception { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -185,7 +185,8 @@ public void testBasic_responseFailure_badRequest() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); @@ -215,7 +216,7 @@ public void testBasic_responseFailure_badURL() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -248,7 +249,7 @@ public void testBasic_redirectCloseChannel() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early From 381b1758621ad268b6ea5f474bfff57e2c1aeafe Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 15:45:32 -0400 Subject: [PATCH 187/337] Modified tests for WebWhois according to changes suggested by laijiang. --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 2 - .../monitoring/blackbox/ProbingAction.java | 1 - .../monitoring/blackbox/WebWhoisModule.java | 10 +- .../blackbox/ProbingActionTest.java | 20 +- .../blackbox/ProbingSequenceTest.java | 120 ++++------- .../monitoring/blackbox/ProbingStepTest.java | 187 ++++++++--------- .../blackbox/TestServers/TestServer.java | 38 ---- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 142 +------------ .../monitoring/blackbox/TokenTest.java | 59 ------ .../blackbox/handlers/ConversionHandler.java | 6 +- .../blackbox/handlers/NettyRule.java | 46 +++- .../handlers/SslClientInitializerTest.java | 5 - .../blackbox/handlers/TestActionHandler.java | 7 +- .../handlers/WebWhoisActionHandlerTest.java | 197 +++++++----------- .../blackbox/messages/TestMessage.java | 4 + .../blackbox/tokens/WebWhoisTokenTest.java | 2 + 18 files changed, 266 insertions(+), 589 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index e12d1f0f522..5ca423c29cc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -30,7 +29,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.sequences(); + ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index fb83b236b69..f9db4865f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,11 +14,9 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 25c3a1c17d6..0265390fafe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -138,7 +138,6 @@ public ChannelFuture call() { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); timer.newTimeout(timeout -> { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 2e640338511..de041afad38 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,14 +17,11 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -33,10 +30,7 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index b5d8f7599c4..ec5ee5d77ec 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,17 +20,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -39,9 +37,9 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; import javax.inject.Provider; import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,10 +72,9 @@ public class ProbingActionTest { public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - + @Ignore @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { + public void testBehavior_existingChannel() { //setup EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -95,7 +92,7 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost("") .build(); @@ -112,6 +109,9 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { String request = ((ByteBuf) msg).toString(UTF_8); assertThat(request).isEqualTo(TEST_MESSAGE); + // Ensures that we haven't marked future as done until response is received. + assertThat(future.isDone()).isFalse(); + //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); assertThat(future.isSuccess()).isTrue(); @@ -143,7 +143,7 @@ public void testSuccess_newChannel() throws Exception { .setBootstrap(bootstrap) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost(ADDRESS_NAME) .build(); @@ -151,7 +151,7 @@ public void testSuccess_newChannel() throws Exception { ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index e5f91a300d6..5c4452df7b3 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -15,17 +15,11 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; -import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; -import google.registry.monitoring.blackbox.TestUtils.TestToken; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import java.net.SocketAddress; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,85 +27,31 @@ @RunWith(JUnit4.class) public class ProbingSequenceTest { - private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new TestToken("") { - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - }; - - private void setupMock(ProbingStep mock, ProbingStep nextStep) { - Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + private ProbingStep setupMock() { + ProbingStep mock = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(mock).nextStep(); + return mock; } - /** - * Custom {@link ProbingStep} subclass that acts as a mock - * step, so we can test how well {@link ProbingSequence} builds - * a linked list of {@link ProbingStep}s from their {@link Builder}s. - */ - - private static class TestStep extends ProbingStep { - private String marker; - - /** We implement all abstract methods to simply return null, as we have no use for them here. */ - @Override - Duration duration() { - return null; - } - @Override - Protocol protocol() { - return null; - } + private static class Wrapper { - @Override - OutboundMessageType messageTemplate() { - return null; - } + T data; - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ - @Override - Bootstrap bootstrap() { - return null; - } - - public TestStep(String marker) { - this.marker = marker; - } - - /** - * On a call to accept, we modify the token to reflect what the current step is, so we can get - * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated - * in order. - */ - @Override - public void accept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - if (!isLastStep) { - nextStep().accept(token); - } else { - ((TestStep)nextStep()).specialAccept(token); - } - } - - /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ - public void specialAccept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - return; + public Wrapper(T data) { + this.data = data; } } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = Mockito.mock(ProbingStep.class); - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) @@ -119,16 +59,25 @@ public void testSequenceBasicConstruction_Success() { .addStep(thirdStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(thirdStep); + assertThat(thirdStep.nextStep()).isEqualTo(firstStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); + assertThat(wrapper.data).isTrue(); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(thirdStep) @@ -137,9 +86,16 @@ public void testSequenceAdvancedConstruction_Success() { .addStep(firstStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(firstStep); + assertThat(thirdStep.nextStep()).isEqualTo(secondStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); + assertThat(wrapper.data).isTrue(); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 256eeb0b29d..91a113940e8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,18 +11,19 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.TestUtils.dummyStep; -import static google.registry.monitoring.blackbox.TestUtils.testStep; -import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; import google.registry.monitoring.blackbox.TestUtils.TestProvider; @@ -30,19 +31,20 @@ import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; +import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; @@ -51,18 +53,18 @@ public class ProbingStepTest { /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final static String ADDRESS_NAME = "TEST_ADDRESS"; + private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final static int PROTOCOL_PORT = 0; + private final static String TEST_MESSAGE = "TEST_MESSAGE"; + private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -73,117 +75,108 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(ADDRESS_NAME); + /** + * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} + * is called, it just marks the supplied future as succeeded, returning the requisite token. + */ + private ProbingStep dummyStep() { + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(dummyStep).nextStep(); + return dummyStep; } - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); - dummyStep = dummyStep(eventLoopGroup); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - } + @Test + public void testNewChannel() throws Exception { + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() + // Sets up Protocol for when we create a new channel. + Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); - } - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) .build(); - } - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - //there should be no next step - assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); - } + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); - @Test - public void testNewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + //Set up blackbox server that receives our messages then echoes them back to us + nettyRule.setUpServer(address); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); + verify(dummyStep, times(1)).accept(any(Token.class)); } + @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupChannel(); - setupExistingChannelToken(); + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); + + // Sets up Protocol for when a channel already exists. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) + .build(); + + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) + .build(); + + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + + // Sets up an embedded channel to contain the two handlers we created already. + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + + //Assures that the channel has a succeeded connectionFuture. + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. + Token testToken = new ExistingChannelToken(channel, ""); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -200,17 +193,13 @@ public void testWithSequence_ExistingChannel() throws Exception { //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); + //At this point, we should have received the message, so the future obtained should be marked + // as a success + verify(dummyStep, times(1)).accept(any(Token.class)); - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index a4474b6b8b5..12e25a6bc6c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -14,24 +14,16 @@ package google.registry.monitoring.blackbox.TestServers; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; - import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform @@ -65,35 +57,5 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index e7f125bb906..4da75b31c25 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -74,7 +75,7 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends ChannelDuplexHandler { + static class RedirectHandler extends SimpleChannelInboundHandler { private String redirectInput; private String destinationInput; @@ -90,8 +91,7 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - HttpRequest request = (HttpRequest) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index ef9926a7620..2567a7cc155 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,42 +16,24 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMethod;; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.concurrent.DefaultPromise; -import java.net.SocketAddress; import javax.inject.Provider; -import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { - static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -76,33 +58,13 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); + response.headers().set("content-type", "text/plain"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); return response; } @@ -121,88 +83,6 @@ public E get() { } } - /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ - public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { - - String message; - - public DuplexMessageTest() { - message = ""; - } - - public DuplexMessageTest(String msg) { - message = msg; - } - - @Override - public String toString() { - return message; - } - - @Override - public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { - message = args[0]; - return this; - } - } - - /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .build(); - - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); - } - - /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { - private DefaultPromise future; - - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; - } - - @Override - public void accept(Token token) { - future.setSuccess(token); - } - public DefaultPromise getFuture() { - return future; - } - - @Override - public String toString() { - return "Dummy Step"; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; @@ -251,21 +131,5 @@ public Channel channel() { return channel; } } - - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java deleted file mode 100644 index 295bb809a13..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) - */ -@RunWith(JUnit4.class) -public class TokenTest { - - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - - public Token webToken = new WebWhoisToken(TEST_DOMAINS); - - @Test - public void testWebToken_MessageModificationSuccess() { - //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); - - //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { - throw new RuntimeException(e); - } - - - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 196141bb875..c9d337d6ad8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -32,7 +32,7 @@ * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +40,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 1d14cf131e6..86b54d9a07d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -25,14 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -44,7 +41,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -55,7 +51,7 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + *

Code based on and almost identical to {@code NettyRule} in the proxy. * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -83,10 +79,12 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + ImmutableList.builder().add(handlers).add(echoHandler).build()); } /** Sets up a client channel connecting to the give local address. */ @@ -124,7 +122,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertThatCustomWorks(String message) throws Exception { + public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -165,6 +163,38 @@ ThrowableSubject assertThatClientRootCause() { } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** + * Saves any inbound error as the cause of the promise failure. + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 83c8e132f07..523fb228752 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -22,12 +22,7 @@ import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 3ecbdcc0d06..95b06e623d1 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -25,17 +25,16 @@ */ public class TestActionHandler extends ActionHandler { - private String receivedMessage; + private InboundMessageType receivedMessage; @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage.toString(); + receivedMessage = inboundMessage; super.channelRead0(ctx, inboundMessage); } - @Override - public String toString() { + public InboundMessageType getResponse() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index f6123045683..d9d1a45ac6e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -20,7 +20,6 @@ import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; -import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; @@ -28,13 +27,11 @@ import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; @@ -56,6 +53,7 @@ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -65,11 +63,12 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of()) + private final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( + null, null, null, null)))) .setName("http") .setPersistentConnection(false) - .setPort(HTTPS_PORT) + .setPort(HTTP_PORT) .build(); @@ -78,14 +77,13 @@ public class WebWhoisActionHandlerTest { private ActionHandler actionHandler; private ProbingAction probingAction; private Provider actionHandlerProvider; + private Protocol initialProtocol; + private HttpRequestMessage msg; - private String generateLocalAddress(String addressString) { - String modifiedAddress = addressString + System.currentTimeMillis(); - address = new LocalAddress(modifiedAddress); - return modifiedAddress; - } - /** Creates default protocol with empty list of handlers and specified other inputs */ + /** + * Creates default protocol with empty list of handlers and specified other inputs + */ private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() .setName(name) @@ -95,7 +93,9 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect .build(); } - /** Initializes new WebWhoisActionHandler */ + /** + * Initializes new WebWhoisActionHandler + */ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, @@ -106,12 +106,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT actionHandlerProvider = new TestProvider<>(actionHandler); } - /** Sets up testing channel with requisite attributes */ + /** + * Sets up testing channel with requisite attributes + */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -119,18 +120,9 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .group(group) .channel(LocalChannel.class); } - /**Sets up probingAction for when testing redirection */ - private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setHost(TARGET_HOST) - .setChannel(channel) - .build(); - } - private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { + private void setupProbingActionWithoutChannel(Protocol protocol, + HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) @@ -140,170 +132,123 @@ private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMess .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + private void setupLocalServer(String redirectInput, String destinationInput, + EventLoopGroup group) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testBasic_responseOk() throws Exception { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { + msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, true); + initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + } + + @Test + public void testBasic_responseOk() { + //setup + setup("", null, true); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure_badRequest() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseBad", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage( + makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same assertThat(future.cause() instanceof FailureException).isTrue(); } - @Test - public void testBasic_responseFailure_badURL() { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseError", 0, true); - setupChannel(initialProtocol, msg); - - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, and event is success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); - } @Test - public void testBasic_redirectCloseChannel() { + public void testBasic_responseFailure_badURL() { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - //checks that future has not been set to successful or a failure - assertThat(testPromise.isSuccess()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - + //assesses that listener is triggered, and event is success + assertThat(future.isDone()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + //ensures Protocol is the same + assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_responseOk() throws UndeterminedStateException { - //setup + public void testAdvanced_redirect() { + // Sets up EventLoopGroup with 1 thread to be blocking. EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + // Sets up embedded channel. + setup("", makeBootstrap(group), false); + setupChannel(initialProtocol, msg); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); - } + // Initializes LocalAddress with unique String. + String host = TARGET_HOST + System.currentTimeMillis(); + address = new LocalAddress(host); - @Test - public void testAdvanced_responseFailure() throws UndeterminedStateException { - //setup - EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); + //stores future + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); + + // Sets up the local server that the handler will be redirected to. setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + FullHttpResponse response = + new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, + HTTP_REDIRECT + host, true, false)); + + //checks that future has not been set to successful or a failure + assertThat(future.isDone()).isFalse(); + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); //assesses that we successfully received good response and protocol is unchanged - assertThrows(FailureException.class, future::syncUninterruptibly); + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index 922c3052bda..c31a9d336bd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,6 +24,10 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; + public TestMessage() { + this(""); + } + public TestMessage(String msg) { message = msg; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index 9a3e755364b..bf5cfc45652 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -19,6 +19,8 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; From 7eae99a3430fdc8fbbff587787fe77007df87b7d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 16:42:43 -0400 Subject: [PATCH 188/337] Removed TestProvider from TestUtils. --- .../blackbox/ProbingActionTest.java | 7 ++-- .../monitoring/blackbox/ProbingStepTest.java | 11 ++---- .../blackbox/TestServers/TestServer.java | 3 -- .../monitoring/blackbox/TestUtils.java | 17 -------- .../handlers/WebWhoisActionHandlerTest.java | 39 +++++++------------ .../blackbox/messages/TestMessage.java | 4 -- 6 files changed, 20 insertions(+), 61 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index ec5ee5d77ec..f7857dd80f9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -64,8 +63,8 @@ public class ProbingActionTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + private Provider testHandlerProvider = () -> testHandler; + private Provider conversionHandlerProvider = () -> conversionHandler; /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -156,7 +155,7 @@ public void testSuccess_newChannel() throws Exception { future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 91a113940e8..1f09dd13553 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -90,9 +89,8 @@ private ProbingStep dummyStep() { @Test public void testNewChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when we create a new channel. Protocol testProtocol = Protocol.builder() @@ -142,9 +140,8 @@ public void testNewChannel() throws Exception { @Test public void testWithSequence_ExistingChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when a channel already exists. Protocol testProtocol = Protocol.builder() diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 12e25a6bc6c..46615a506fb 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -29,15 +29,12 @@ * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { - private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - this.localAddress = localAddress; - //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 2567a7cc155..50c60d9fc52 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -21,7 +21,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -29,7 +28,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Provider; /** Utility class for various helper methods used in testing. */ public class TestUtils { @@ -68,21 +66,6 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ - public static class TestProvider implements Provider { - - private E obj; - - public TestProvider(E obj) { - this.obj = obj; - } - - @Override - public E get() { - return obj; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index d9d1a45ac6e..cd85dd08df8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -22,10 +22,8 @@ import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; @@ -64,18 +62,16 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( - null, null, null, null)))) + .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( + null, null, null, null))) .setName("http") .setPersistentConnection(false) .setPort(HTTP_PORT) .build(); - private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; - private ProbingAction probingAction; private Provider actionHandlerProvider; private Protocol initialProtocol; private HttpRequestMessage msg; @@ -103,13 +99,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT STANDARD_PROTOCOL, messageTemplate ); - actionHandlerProvider = new TestProvider<>(actionHandler); + actionHandlerProvider = () -> actionHandler; } /** * Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + private void setupChannel(Protocol protocol) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -121,19 +117,8 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } - private void setupProbingActionWithoutChannel(Protocol protocol, - HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(addressString) - .build(); - } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group) { + EventLoopGroup group, LocalAddress address) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } @@ -148,7 +133,9 @@ private void setup(String hostName, Bootstrap bootstrap, boolean persistentConne public void testBasic_responseOk() { //setup setup("", null, true); - setupChannel(initialProtocol, msg); + + setupChannel(initialProtocol); + //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); @@ -168,7 +155,7 @@ public void testBasic_responseOk() { public void testBasic_responseFailure_badRequest() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -194,7 +181,7 @@ public void testBasic_responseFailure_badRequest() { public void testBasic_responseFailure_badURL() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -223,18 +210,18 @@ public void testAdvanced_redirect() { // Sets up embedded channel. setup("", makeBootstrap(group), false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); // Initializes LocalAddress with unique String. String host = TARGET_HOST + System.currentTimeMillis(); - address = new LocalAddress(host); + LocalAddress address = new LocalAddress(host); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group); + setupLocalServer("", host, group, address); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index c31a9d336bd..922c3052bda 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,10 +24,6 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; - public TestMessage() { - this(""); - } - public TestMessage(String msg) { message = msg; } From 891215a3e1d7addef419c3b7548628d4c5af24ba Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 189/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 2 +- .../google/registry/xjc/package-info.java | 2 +- prober/build.gradle | 5 - .../monitoring/blackbox/NewChannelAction.java | 136 +++++++++ .../registry/monitoring/blackbox/Prober.java | 19 +- .../monitoring/blackbox/ProbingAction.java | 265 ++++++------------ .../handlers/ServerSideException.java | 15 + .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 117 +++----- .../blackbox/messages/HttpRequestMessage.java | 63 +---- .../messages/HttpResponseMessage.java | 44 +-- .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 15 files changed, 320 insertions(+), 365 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/prober/build.gradle b/prober/build.gradle index 478d33e1ef9..d0ac4ff3b51 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -20,8 +20,6 @@ dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] @@ -33,9 +31,6 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..0ba3a0c22be --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 5ca423c29cc..333330207f1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,26 +14,17 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 0265390fafe..2441debb12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,27 +14,14 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -47,7 +34,7 @@ import javax.inject.Provider; /** - * AutoValue class that represents action generated by {@link ProbingStep} + *Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -57,27 +44,36 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

*/ -@AutoValue + public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; + } /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); + /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -85,177 +81,92 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ - @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); - /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> finished.setSuccess(), + future -> { + if (!protocol().persistentConnection()) { + + //If we created a new channel for this action, close the connection to the channel + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } /** - * Performs the work of the actual action + * The method that sends the {@code outboundMessage} down the channel pipeline * - *

First, checks if channel is active by setting a listener to perform the bulk of the work - * when the connection future is successful.

- * - *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

- * - *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

- * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. + * @return future that denotes when the action has been successfully performed */ - - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override public ChannelFuture call() { - //ChannelPromise that we return - ChannelPromise finished = channel().newPromise(); - //Ensures channel has been set up with connection future as an attribute - checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); - - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture connectionFuture) -> { - if (connectionFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - - ActionHandler actionHandler; - try { - actionHandler = channel().pipeline().get(ActionHandler.class); - } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); - - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> { - if (future.isSuccess()) { - finished.setSuccess(); - } else { - finished.setFailure(future.cause()); - } - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) { - logger.atInfo() - .log("Closed stale channel. Moving on to next ProbingStep"); - } else { - logger.atWarning() - .log( - "Could not close channel. Stale connection still exists."); - } - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(connectionFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ - @AutoValue.Builder - public abstract static class Builder { - private Bootstrap bootstrap; - - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); } - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setHost(String value); - - public abstract Builder setChannel(Channel channel); - - abstract Protocol protocol(); + //ChannelPromise that we use to inform ProbingStep when we are finished. + ChannelPromise finished = channel().newPromise(); - abstract Channel channel(); + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } - abstract String host(); + return finished; + } - abstract ProbingAction autoBuild(); + public abstract static class Builder, P extends ProbingAction> { - public ProbingAction build() { - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - address = new LocalAddress(host()); - } + public abstract B delay(Duration value); - checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); - //If a channel is supplied, nothing is needed to be done + public abstract B outboundMessage(OutboundMessageType value); - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel() == null) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); + public abstract B protocol(Protocol value); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); + public abstract B host(String value); - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } + public abstract B path(String value); - //now we can actually build the ProbingAction - return autoBuild(); - } - } + public abstract P build(); - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); } /** @@ -265,27 +176,11 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - private static void addHandlers( + static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { channelPipeline.addLast(handlerProvider.get()); } } - - - - @Override - public String toString() { - return String.format( - "ProbingAction with delay: %d\n" + - "outboundMessage: %s\n" + - "protocol: %s\n" + - "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index 919006592ea..ac844ac99df 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,8 +15,7 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -90,8 +89,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - String host = channel.attr(REMOTE_ADDRESS_KEY).get(); + ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); + Protocol protocol = action.protocol(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -104,7 +103,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), host, protocol.port()); + .newHandler(channel.alloc(), action.host(), protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 34eac2a0118..21010f0e887 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,23 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -47,53 +48,30 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ - private final Bootstrap bootstrap; - - /** {@link Protocol} for when redirected to http endpoint. */ - private final Protocol httpWhoisProtocol; - - /** {@link Protocol} for when redirected to https endpoint. */ - private final Protocol httpsWhoisProtocol; - - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } + public WebWhoisActionHandler() {} /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { + throws ServerSideException { HttpResponseMessage response = (HttpResponseMessage) msg; + if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - //On success, we always pass message to ActionHandler's channelRead0 method. - super.channelRead0(ctx, msg); + finished.setSuccess(); + + logger.atInfo().log("Response Received: " + response); - } else if (response.headers().get("location") != null) { + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { //Obtain url to be redirected to URL url; @@ -101,68 +79,55 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); + int newPort = url.getDefaultPort(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, url.getDefaultPort(), newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException("Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); - } + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) .build(); + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } + logger.atInfo().log("Successfully Closed Connection"); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE + finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 5e9300d0f34..3fb8c187ad9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -19,28 +5,19 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; -/** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. - * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + @Override @@ -49,33 +26,15 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } - - /** Modifies headers to reflect new host and new path if applicable. */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) - setUri(args[1]); - - return this; + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + ByteBuf buf = request.content(); + if (buf == null) { + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - throw new IllegalArgumentException( - String.format( - "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + args, args.length)); + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - } - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index f1b2d6ac6a7..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,19 +6,33 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} - */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { + super(version, status); + } + + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); + + return finalResponse; } + + + } diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From 618be06014f7f88804564ec5d8fd46e6e8c86e02 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:58:52 -0400 Subject: [PATCH 190/337] Fixed changes suggested by CydeWeys --- prober/build.gradle | 37 +-- .../monitoring/blackbox/Protocol.java | 87 +++++-- .../blackbox/exceptions/FailureException.java | 15 +- .../blackbox/handlers/ActionHandler.java | 91 +++---- .../handlers/WebWhoisActionHandlerTest.java | 222 ++++++++---------- 5 files changed, 224 insertions(+), 228 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index d0ac4ff3b51..259b093e35e 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,30 +16,35 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 624f08fd4e9..371b3c3e8d7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,28 +16,81 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; import javax.inject.Provider; /** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. + * Protocol Class packages all static variables necessary for a certain type of connection + * Both the host and the path can be changed for the same protocol + * Mainly packages the handlers necessary for the requisite channel pipeline */ @AutoValue public abstract class Protocol { - /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ - public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + + /** + * Default names associated with each protocol + */ + final static String EPP_PROTOCOL_NAME = "EPP"; + final static String DNS_PROTOCOL_NAME = "DNS"; + final static String WHOIS_PROTOCOL_NAME = "WHOIS"; + final static String RDAP_PROTOCOL_NAME = "RDAP"; + + private String host; + private String path = ""; + private ProbingAction probingAction; + + /** Setter method for Protocol's host*/ + public Protocol host(String host) { + this.host = host; + return this; + } + + /** Getter method for Protocol's host*/ + public String host() { + return host; + } + + /** Setter method for Protocol's path*/ + public Protocol path(String path) { + this.path = path; + return this; + } + + /** Getter method for Protocol's path*/ + public String path() { + return path; + } + /** Setter method for Protocol's ProbingAction parent*/ + public Protocol probingAction(ProbingAction probingAction) { + this.probingAction = probingAction; + return this; + } + + /** Getter method for Protocol's path*/ + public ProbingAction probingAction() { + return probingAction; + } + + /** If connection associated with Protocol is persistent, which is only EPP */ + public boolean persistentConnection() { + return name() == EPP_PROTOCOL_NAME; + } + + /** Protocol Name */ public abstract String name(); + /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - abstract ImmutableList> handlerProviders(); + public abstract ImmutableList> handlerProviders(); - /** Boolean that notes if connection associated with Protocol is persistent.*/ - abstract boolean persistentConnection(); + + public abstract Builder toBuilder(); public static Builder builder() { return new AutoValue_Protocol.Builder(); @@ -47,25 +100,13 @@ public static Builder builder() { @AutoValue.Builder public abstract static class Builder { - public abstract Builder setName(String value); - - public abstract Builder setPort(int num); + public abstract Builder name(String value); - public abstract Builder setHandlerProviders(ImmutableList> providers); + public abstract Builder port(int num); - public abstract Builder setPersistentConnection(boolean value); + public abstract Builder handlerProviders(ImmutableList> providers); public abstract Protocol build(); } - - @Override - public String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); - } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 36687e7ac82..9f716bb2589 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,18 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.exceptions; +package google.registry.monitoring.blackbox; -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class FailureException extends Exception { - - public FailureException(String msg) { - super(msg); - } - - public FailureException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index ab628ed064f..3fa60cd844a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,86 +15,69 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; +import com.google.common.flogger.StackSize; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.HttpResponse; +import java.util.function.Function; +import javax.inject.Inject; /** - *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

- * - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} - * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

- * - *

Subclasses specify further work to be done for specific kinds of channel pipelines.

+ * @param Generic Type of Inbound Message + * @param Generic Type of Outbound Message + * Abstract class that tells sends message down pipeline and + * and tells listeners to move on when the message is received. */ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +public abstract class ActionHandler extends SimpleChannelInboundHandler + implements Function { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link ChannelPromise} that informs {@link ProbingAction} if response has been received. */ - private ChannelPromise finished; + protected ChannelPromise finished; + private Channel channel; + - /** Returns initialized {@link ChannelPromise} to {@link ProbingAction}.*/ - public ChannelFuture getFinishedFuture() { + /** returns ChannelPromise for when inbound message is recieved + * a + * @param outboundMessage + * @return + */ + @Override + public ChannelFuture apply(O outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + + channel.writeAndFlush(outboundMessage); return finished; + + } + + public void resetFuture() { + finished = channel.newPromise(); } - /** Initializes {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { - // Once handler is added to channel pipeline, initialize channel and future for this handler + //Once handler is added to channel pipeline, initialize channel and future for this handler + + channel = ctx.channel(); finished = ctx.newPromise(); } - /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ + //Only purpose of Handler is to mark future as a success finished.setSuccess(); } - /** - * Logs the channel and pipeline that caused error, closes channel, then informs - * {@link ProbingAction} listeners of error. - */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atWarning().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); - - if (cause instanceof FailureException) { - //On FailureException, we know the response is a failure. - - //Since it wasn't a success, we still want to log to see what caused the FAILURE - logger.atInfo().log(cause.getMessage()); - - //As always, inform the ProbingStep that we successfully completed this action - finished.setFailure(cause); - - } else { - //On UndeterminedStateException, we know the response type is an error. - - //Since it wasn't a success, we still log what caused the ERROR - logger.atWarning().log(cause.getMessage()); - finished.setFailure(cause); - - //As this was an ERROR in performing the action, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } + logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } } + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index cd85dd08df8..63bb2cf5b53 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,43 +15,34 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelPromise; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@link WebWhoisActionHandler}. - * - *

Attempts to test how well {@link WebWhoisActionHandler} works - * when responding to all possible types of responses

- */ +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -59,183 +50,172 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; - private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( - null, null, null, null))) - .setName("http") - .setPersistentConnection(false) - .setPort(HTTP_PORT) - .build(); private EmbeddedChannel channel; private ActionHandler actionHandler; - private Provider actionHandlerProvider; - private Protocol initialProtocol; - private HttpRequestMessage msg; - - /** - * Creates default protocol with empty list of handlers and specified other inputs - */ - private Protocol createProtocol(String name, int port, boolean persistentConnection) { + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() - .setName(name) - .setPort(port) - .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) - .setPersistentConnection(persistentConnection) - .build(); + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); } - /** - * Initializes new WebWhoisActionHandler - */ - private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { - actionHandler = new WebWhoisActionHandler( - bootstrap, - STANDARD_PROTOCOL, - STANDARD_PROTOCOL, - messageTemplate - ); - actionHandlerProvider = () -> actionHandler; + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); } - /** - * Sets up testing channel with requisite attributes - */ + /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol) { + setupActionHandler(); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - private Bootstrap makeBootstrap(EventLoopGroup group) { - return new Bootstrap() - .group(group) - .channel(LocalChannel.class); + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group, LocalAddress address) { - WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); } - private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { - msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); - setupActionHandler(bootstrap, msg); - initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; } + @Test - public void testBasic_responseOk() { + public void testSuccess_responseOk() { //setup - setup("", null, true); - + Protocol initialProtocol = createProtocol("responseOk", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badRequest() { + public void testSuccess_responseBad() { //setup - setup("", null, false); + Protocol initialProtocol = createProtocol("responseBad", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage( - makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(future.isDone()).isTrue(); + assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badURL() { + public void testSuccess_redirectCloseChannel() { //setup - setup("", null, false); - setupChannel(initialProtocol); + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, and event is success - assertThat(future.isDone()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_redirect() { - // Sets up EventLoopGroup with 1 thread to be blocking. - EventLoopGroup group = new NioEventLoopGroup(1); - - // Sets up embedded channel. - setup("", makeBootstrap(group), false); - setupChannel(initialProtocol); - - // Initializes LocalAddress with unique String. - String host = TARGET_HOST + System.currentTimeMillis(); - LocalAddress address = new LocalAddress(host); + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group, address); - FullHttpResponse response = - new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + host, true, false)); + channel.writeInbound(originalResponse); - //checks that future has not been set to successful or a failure - assertThat(future.isDone()).isFalse(); + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); - channel.writeInbound(response); + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } + } From 0ad9ace09cebbc65dab3b8bf4e9c87e3f54b7741 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 191/337] Added missing license headers and JavaDoc --- .../handlers/ServerSideException.java | 16 ++++++- .../blackbox/messages/HttpRequestMessage.java | 45 ++++++++++++++----- .../messages/HttpResponseMessage.java | 32 ++++++++++--- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java index 5d3addb920e..441062a9e7b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; /** @@ -12,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 3fb8c187ad9..8fbb55c6339 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,13 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} + * (but needs to implement {@link OutboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion + * from {@link FullHttpRequest} to its type

+ */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +35,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,15 +42,22 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - if (buf == null) { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //creates message based on content found in original request + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //stores headers from request in finalRequest + request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); + + return finalRequest; + + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..776e7de0824 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,11 +1,33 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} + * (but needs to implement {@link InboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion + * from {@link FullHttpResponse} to its type

+ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -17,22 +39,20 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } + /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); + //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + //stores headers from response in finalResponse + response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); return finalResponse; } - - - } From dccedaa50362947bc04429dbbba3fb2feddea55c Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 192/337] Minor fix in NewChannelAction JavaDoc --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..1e7578d5679 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; - import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -28,8 +27,7 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) */ @AutoValue public abstract class NewChannelAction extends ProbingAction { From 59ea21df57d0d6f188e483e7ec51eae0a93f1708 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 13:33:23 -0400 Subject: [PATCH 193/337] Minor Style Fix --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 ---- .../java/google/registry/monitoring/blackbox/Protocol.java | 1 - .../registry/monitoring/blackbox/handlers/ActionHandler.java | 1 - .../monitoring/blackbox/handlers/WebWhoisActionHandler.java | 2 -- 4 files changed, 8 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..84cf75492f2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -52,7 +52,6 @@ public Channel channel() { return this.channel; } - @Override public abstract Builder toBuilder(); @@ -120,7 +119,6 @@ public static NewChannelAction.Builder builder() return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -129,6 +127,4 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 371b3c3e8d7..4b0727229c1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -109,4 +109,3 @@ public abstract static class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 3fa60cd844a..503d211b324 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -80,4 +80,3 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 21010f0e887..5b77461cd8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -131,7 +131,5 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } } - - } From c3c83bb6bb4b7ca4b4f803095cb4b1b5bfafa602 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 194/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 70 ++--- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 17 +- .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProberModule.java | 83 ++++-- .../monitoring/blackbox/ProbingAction.java | 17 +- .../monitoring/blackbox/ProbingSequence.java | 117 +++++---- .../monitoring/blackbox/ProbingStep.java | 177 ++++++------- .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 12 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 ++++ .../monitoring/blackbox/WebWhoisModule.java | 170 ++++++------ .../exceptions/EppClientException.java | 29 ++ .../exceptions/InternalException.java | 29 ++ .../exceptions/ResponseException.java | 29 ++ .../ServerSideException.java | 4 +- .../blackbox/handlers/ActionHandler.java | 88 ++++--- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/WebWhoisActionHandler.java | 19 +- .../handlers/WebWhoisMessageHandler.java | 31 +-- .../blackbox/messages/HttpRequestMessage.java | 50 +--- .../messages/HttpResponseMessage.java | 32 +-- .../messages/OutboundMessageType.java | 11 +- .../blackbox/ProbingActionTest.java | 158 +++++------ .../blackbox/ProbingSequenceStepTest.java | 219 ++++++++++++++++ .../blackbox/TestServers/TestServer.java | 57 ++-- .../blackbox/TestServers/WebWhoisServer.java | 33 +-- .../monitoring/blackbox/TestUtils.java | 144 +++++++++- .../monitoring/blackbox/TokenTest.java | 60 +++++ .../blackbox/handlers/ConversionHandler.java | 11 +- .../blackbox/handlers/NettyRule.java | 62 +---- .../handlers/SslClientInitializerTest.java | 49 +++- .../blackbox/handlers/TestActionHandler.java | 15 +- .../handlers/WebWhoisActionHandlerTest.java | 247 +++++++++++++----- 36 files changed, 1589 insertions(+), 712 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/build.gradle b/prober/build.gradle index 259b093e35e..e48eacb8bf9 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -17,40 +17,42 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { - def deps = rootProject.dependencyMap - - compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] - compile deps['com.google.dagger:dagger'] - compile deps['com.google.flogger:flogger'] - compile deps['com.google.guava:guava'] - compile deps['io.netty:netty-buffer'] - compile deps['io.netty:netty-codec-http'] - compile deps['io.netty:netty-codec'] - compile deps['io.netty:netty-common'] - compile deps['io.netty:netty-handler'] - compile deps['io.netty:netty-transport'] - compile deps['javax.inject:javax.inject'] - compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - - runtime deps['com.google.flogger:flogger-system-backend'] - runtime deps['com.google.auto.value:auto-value'] - runtime deps['io.netty:netty-tcnative-boringssl-static'] - - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') - - // Include auto-value in compile until nebula-lint understands - // annotationProcessor - annotationProcessor deps['com.google.auto.value:auto-value'] - testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] + def deps = rootProject.dependencyMap + + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] + compile deps['com.google.dagger:dagger'] + compile deps['com.google.flogger:flogger'] + compile deps['com.google.guava:guava'] + compile deps['io.netty:netty-buffer'] + compile deps['io.netty:netty-codec-http'] + compile deps['io.netty:netty-codec'] + compile deps['io.netty:netty-common'] + compile deps['io.netty:netty-handler'] + compile deps['io.netty:netty-transport'] + compile deps['javax.inject:javax.inject'] + compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] + + runtime deps['com.google.flogger:flogger-system-backend'] + runtime deps['com.google.auto.value:auto-value'] + runtime deps['io.netty:netty-tcnative-boringssl-static'] + + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') + //testCompile project(path: ':core', configuration: 'testRuntime') + + // Include auto-value in compile until nebula-lint understands + // annotationProcessor + annotationProcessor deps['com.google.auto.value:auto-value'] + testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 84cf75492f2..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -52,6 +53,7 @@ public Channel channel() { return this.channel; } + @Override public abstract Builder toBuilder(); @@ -83,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -116,9 +118,10 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } + @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -127,4 +130,6 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } + } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 333330207f1..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,16 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index f9db4865f78..73bd9127852 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,68 +14,99 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import io.netty.channel.Channel; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SslProvider; import java.util.Set; import javax.inject.Singleton; -import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores - * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. + * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} + * + *

Provides

*/ @Module public class ProberModule { + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; - /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - - /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides - @Singleton - Class provideChannelClazz() { - return NioSocketChannel.class; + @HttpWhoisProtocol + ProbingSequence provideHttpWhoisSequence( + @HttpWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ + @Provides - @Singleton - Duration provideDuration() { - return DEFAULT_DURATION; + @HttpsWhoisProtocol + ProbingSequence provideHttpsWhoisSequence( + @HttpsWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; + } + + @Provides + @HttpsWhoisProtocol + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } - /** Root level {@link Component} that provides each {@link ProbingSequence}. */ + @Provides + ImmutableMap providePortToProtocolMap( + Set protocolSet) { + return Maps.uniqueIndex(protocolSet, Protocol::port); + } + + + @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, + TokenModule.class }) public interface ProberComponent { - //Standard WebWhois sequence - Set sequences(); + @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); + + @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); + + ImmutableMap providePortToProtocolMap(); + + @WebWhoisProtocol Token provideWebWhoisToken(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2441debb12d..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -34,7 +34,7 @@ import javax.inject.Provider; /** - *Superclass that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -183,4 +183,19 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + @Override + public String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n" + + "path: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host(), + path() + ); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 91c4165c068..6387207fea4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,86 +14,109 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. + * Represents Sequence of {@link ProbingSteps} that the Prober performs in order * + * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} + * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /**Each {@link ProbingSequence} requires a start token to begin running. */ - private Token startToken; + /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ + private EventLoopGroup eventGroup; - public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ + private Bootstrap bootstrap; + + public Bootstrap getBootstrap() { + return bootstrap; + } + + public void start(Token token) { + // calls the first step with input token; + firstStep.accept(token); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * {@link Builder} which takes in {@link ProbingStep}s + * + * @param Same specified {@code C} for overall {@link ProbingSequence} */ - public static class Builder { - - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - - private Token startToken; - - public Builder(Token startToken) { - this.startToken = startToken; + public static class Builder { + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstSequenceStep; + private EventLoopGroup eventLoopGroup; + private Class classType; + + Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; + return this; } - /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, - * built, and pointed to by the previous {@link ProbingStep} added. - */ - public Builder addStep(ProbingStep step) { - - if (currentStep == null) + Builder addStep(ProbingStep step) { + if (currentStep == null) { firstStep = step; - else + } else { currentStep.nextStep(step); - + } currentStep = step; return this; } - /** We take special note of the first repeated step. */ - public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; + /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ + Builder makeFirstRepeated() { + firstSequenceStep = currentStep; + return this; + } + /** Set the class to be the same as {@code C} */ + public Builder setClass(Class classType) { + this.classType = classType; return this; } - /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and - * calls private constructor to create {@link ProbingSequence}. - */ - public ProbingSequence build() { - if (firstRepeatedStep == null) - firstRepeatedStep = firstStep; - - currentStep.nextStep(firstRepeatedStep); + public ProbingSequence build() { + currentStep.nextStep(firstSequenceStep); currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); } + } - private ProbingSequence(ProbingStep firstStep, Token startToken) { + /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ + private void setParents() { + ProbingStep currentStep = firstStep.parent(this).nextStep(); + + while (currentStep != firstStep) { + currentStep = currentStep.parent(this).nextStep(); + } + } + private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, + Class classType) { this.firstStep = firstStep; - this.startToken = startToken; + this.eventGroup = eventLoopGroup; + this.bootstrap = new Bootstrap() + .group(eventGroup) + .channel(classType); + setParents(); + } + + @Override + public String toString() { + return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 3df536a9478..5bad5abf6bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,164 +14,155 @@ package google.registry.monitoring.blackbox; -import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.io.IOException; import java.util.function.Consumer; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step - * in {@link ProbingSequence}. + * Represents generator of actions performed at each step in {@link ProbingSequence} + * + * @param See {@code C} in {@link ProbingSequence} * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. - * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, - * generates a new {@link ProbingAction} to call.

+ * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies + * these components on each loop iteration with the consumed {@link Token} and from that, + * generates new {@link ProbingAction} to perform<./p> * + *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -@AutoValue -public abstract class ProbingStep implements Consumer { +public abstract class ProbingStep implements Consumer { + public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); + protected static final Duration DEFAULT_DURATION = new Duration(2000L); private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Necessary boolean to inform when to obtain next {@link Token}*/ - protected boolean isLastStep = false; - private ProbingStep nextStep; - - /** Time delay duration between actions. */ - abstract Duration duration(); - - /** {@link Protocol} type for this step. */ - abstract Protocol protocol(); - - /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ - abstract OutboundMessageType messageTemplate(); - - /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ - abstract Bootstrap bootstrap(); - + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + protected LocalAddress address = DEFAULT_ADDRESS; - @AutoValue.Builder - public static abstract class Builder { - public abstract Builder setDuration(Duration value); + /** Necessary boolean to inform when to obtain next {@link Token}*/ + private boolean isLastStep = false; + private ProbingStep nextStep; + private ProbingSequence parent; - public abstract Builder setProtocol(Protocol value); + protected Duration duration; - public abstract Builder setMessageTemplate(OutboundMessageType value); + protected final Protocol protocol; + protected final OutboundMessageType message; - public abstract Builder setBootstrap(Bootstrap value); + protected ProbingStep(Protocol protocol, OutboundMessageType message) { + this.protocol = protocol; + this.message = message; + } - public abstract ProbingStep build(); + private OutboundMessageType message() { + return message; } - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); + Protocol protocol() { + return protocol; } + void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { - OutboundMessageType message = token.modifyMessage(messageTemplate()); - ProbingAction.Builder probingActionBuilder = ProbingAction.builder() - .setDelay(duration()) - .setProtocol(protocol()) - .setOutboundMessage(message) - .setHost(token.host()); - - if (token.channel() != null) - probingActionBuilder.setChannel(token.channel()); - else - probingActionBuilder.setBootstrap(bootstrap()); - - return probingActionBuilder.build(); + ProbingStep parent(ProbingSequence parent) { + this.parent = parent; + return this; } + /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + private ProbingAction generateAction(Token token) throws InternalException { + ProbingAction generatedAction; + + OutboundMessageType message = token.modifyMessage(message()); + + //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction + if (protocol().persistentConnection() && token.channel() != null) { + generatedAction = ExistingChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .channel(token.channel()) + .build(); + } else { + generatedAction = NewChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .bootstrap(parent.getBootstrap()) + .address(address) + .build(); + + } + return generatedAction; + } - /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ + + /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

- */ @Override public void accept(Token token) { - ProbingAction currentAction; + ProbingAction nextAction; //attempt to generate new action. On error, move on to next step try { - currentAction = generateAction(token); - } catch(UndeterminedStateException e) { + nextAction = generateAction(token); + } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch(Exception e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; + //If the next step maintains the connection, pass on the channel from this + if (protocol().persistentConnection()) { + token.channel(nextAction.channel()); } + //call the created action + ChannelFuture future = nextAction.call(); + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - + nextStep.accept(generateNextToken(token)); } else { - //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - - if (protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n", + "OutboundMessage: %s\n" + + "and parent sequence: %s", protocol(), - messageTemplate().getClass().getName()); + message(), + parent); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 4b0727229c1..24c666b8d9d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -108,4 +108,16 @@ public abstract static class Builder { public abstract Protocol build(); } + + @Override + public String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index de041afad38..dba905c0e49 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,96 +18,90 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; + +import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; - private static final String HTTP_PROTOCOL_NAME = "http"; - private static final String HTTPS_PROTOCOL_NAME = "https"; - - /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ - private static final int maximumMessageLengthBytes = 512 * 1024; + final static String DOMAIN_SUFFIX = "whois.nic."; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpWhoisProtocol {} + @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpsWhoisProtocol {} + @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - /** {@link Provides} standard WebWhois sequence. */ + + + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + + @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { + @HttpWhoisProtocol + static ProbingStep provideHttpWhoisProbingSequence( + @HttpWhoisProtocol Protocol httpWhoisProtocol) { + return new ProbingStepWeb<>(httpWhoisProtocol); + } - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); + @Provides + @HttpsWhoisProtocol + static ProbingStep provideHttpsWhoisProbingStep( + @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { + return new ProbingStepWeb<>(httpsWhoisProtocol); } - /** {@link Provides} only step used in WebWhois sequence. */ + @Singleton @Provides - @WebWhoisProtocol - static ProbingStep provideWebWhoisStep( - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @WebWhoisProtocol Bootstrap bootstrap, - HttpRequestMessage messageTemplate, - Duration duration) { - - return ProbingStep.builder() - .setProtocol(httpWhoisProtocol) - .setBootstrap(bootstrap) - .setMessageTemplate(messageTemplate) - .setDuration(duration) + @HttpWhoisProtocol + static Protocol provideHttpWhoisProtocol( + @HttpWhoisProtocol int httpWhoisPort, + @HttpWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides - @HttpWhoisProtocol - static Protocol provideHttpWhoisProtocol( + @IntoSet + static Protocol provideHttpProtocolForSet( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTP_PROTOCOL_NAME) - .setPort(httpWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ + @Singleton @Provides @HttpsWhoisProtocol @@ -115,21 +109,40 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTPS_PROTOCOL_NAME) - .setPort(httpsWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } + @Singleton + @Provides + @IntoSet + static Protocol provideHttpsProtocolForSet( + @HttpsWhoisProtocol int httpsWhoisPort, + @HttpsWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Provides + @WebWhoisProtocol + String provideHttpWhoisHost() { + return "app"; + } + - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -138,14 +151,13 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -155,60 +167,34 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } - @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); - } - - @Provides - static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { - return new HttpObjectAggregator(maxContentLength); - } - - /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ - @Provides - @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); - } - /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ - @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap( - EventLoopGroup eventLoopGroup, - Class channelClazz){ - return new Bootstrap() - .group(eventLoopGroup) - .channel(channelClazz); + static MessageHandler provideMessageHandler() { + return new WebWhoisMessageHandler(); } @Provides - @WebWhoisProtocol - int provideMaximumMessageLengthBytes() { - return maximumMessageLengthBytes; + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); } - /** {@link Provides} the list of top level domains to be probed */ - @Singleton @Provides - @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); + static HttpObjectAggregator provideHttpObjectAggregator() { + return new HttpObjectAggregator(1048576); } @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return HTTP_WHOIS_PORT; + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } @Provides @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return HTTPS_WHOIS_PORT; + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 503d211b324..7898203e92d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,68 +15,88 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import com.google.common.flogger.StackSize; -import io.netty.channel.ChannelInboundHandlerAdapter; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpResponse; -import java.util.function.Function; -import javax.inject.Inject; /** + *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - * @param Generic Type of Inbound Message - * @param Generic Type of Outbound Message - * Abstract class that tells sends message down pipeline and - * and tells listeners to move on when the message is received. + *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

+ * + *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} + * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception + * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses + * specify further work to be done for specific kinds of channel pipelines.

*/ -public abstract class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - protected ChannelPromise finished; - private Channel channel; + /** Three types of responses received down pipeline */ + public enum ResponseType {SUCCESS, FAILURE, ERROR} + /** Status of response for current {@link ActionHandler} instance */ + private static ResponseType status; - /** returns ChannelPromise for when inbound message is recieved - * a - * @param outboundMessage - * @return - */ - @Override - public ChannelFuture apply(O outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline + protected ChannelPromise finished; - channel.writeAndFlush(outboundMessage); + /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + public ChannelFuture getFuture() { return finished; - - } - - public void resetFuture() { - finished = channel.newPromise(); } + /** Initializes new {@link ChannelPromise} */ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler - - channel = ctx.channel(); finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ - //Only purpose of Handler is to mark future as a success - + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + //simply marks finished as success + status = ResponseType.SUCCESS; finished.setSuccess(); } + /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); + logger.atSevere().withCause(cause).log(String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), + ctx.channel().pipeline().toString())); + + + if (ResponseException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + status = ResponseType.FAILURE; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (ServerSideException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + status = ResponseType.ERROR; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (InternalException.class.isInstance(cause)){ + logger.atSevere().withCause(cause).log("Severe internal error"); + finished.setFailure(cause); + } else { + finished.setFailure(cause); + } + + //due to failure, close channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 5b77461cd8f..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -17,20 +17,16 @@ import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; @@ -59,7 +55,7 @@ public WebWhoisActionHandler() {} */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ServerSideException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -67,9 +63,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - finished.setSuccess(); - logger.atInfo().log("Response Received: " + response); + super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -79,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -126,10 +121,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + throw new ResponseException("Response received from remote site was: " + response.status()); } } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 58c395ad86e..4afc5d95ba7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,52 +1,33 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -/** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} - * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection. - */ -public class WebWhoisMessageHandler extends ChannelDuplexHandler { +public class WebWhoisMessageHandler extends MessageHandler { + + private HttpRequestMessage request; @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - HttpRequestMessage request = (HttpRequestMessage) msg; + request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + FullHttpResponse originalResponse = (FullHttpResponse) msg; - HttpResponseMessage response = new HttpResponseMessage(originalResponse); + InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8fbb55c6339..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,13 +6,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} - * (but needs to implement {@link OutboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion - * from {@link FullHttpRequest} to its type

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -35,6 +14,11 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + + @Override public HttpRequestMessage setUri(String path) { @@ -42,22 +26,16 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - - //creates message based on content found in original request - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - - - //stores headers from request in finalRequest - request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - - return finalRequest; - + HttpRequestMessage output; + if (buf == null) { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + } else { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + } + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 776e7de0824..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,33 +1,11 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} - * (but needs to implement {@link InboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion - * from {@link FullHttpResponse} to its type

- */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -39,20 +17,22 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } - /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); - //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - //stores headers from response in finalResponse - response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); return finalResponse; } + + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 6e3da3f69d2..0dd17e9d4a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,17 +14,8 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; - /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType { - - /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; +public interface OutboundMessageType {} - /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - @Override - String toString(); -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index f7857dd80f9..cbcf2fc82b0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,19 +15,20 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -38,7 +39,6 @@ import io.netty.channel.nio.NioEventLoopGroup; import javax.inject.Provider; import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,65 +51,99 @@ * */ @RunWith(JUnit4.class) public class ProbingActionTest { - private static final String TEST_MESSAGE = "MESSAGE_TEST"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final int TEST_PORT = 0; - - private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + /** Necessary Constants for test */ + private final String TEST_MESSAGE = "MESSAGE_TEST"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final int TEST_PORT = 0; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = () -> testHandler; - private Provider conversionHandlerProvider = () -> conversionHandler; + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + private ProbingAction newChannelAction; + private ProbingAction existingChannelAction; + private EmbeddedChannel channel; + private Protocol protocol; /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); + /** Sets up a {@link Protocol} corresponding to when a new connection is created */ + private void setupNewChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(false) + .build(); + } + /** Sets up a {@link Protocol} corresponding to when a new connection exists */ + private void setupExistingChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(true) + .build(); + } + + /** Sets up a {@link NewChannelAction} with test specified attributes */ + private void setupNewChannelAction() { + newChannelAction = NewChannelAction.builder() + .bootstrap(bootstrap) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .address(address) + .build(); + } + + private void setupChannel() { + channel = new EmbeddedChannel(); + } + + /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + private void setupExistingChannelAction(Channel channel) { + existingChannelAction = ExistingChannelAction.builder() + .channel(channel) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .build(); + } - @Ignore @Test public void testBehavior_existingChannel() { //setup - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up a Protocol corresponding to when a connection exists. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(true) - .build(); + setupChannel(); + setupExistingChannelProtocol(); + setupExistingChannelAction(channel); + channel.pipeline().addLast(conversionHandler); + channel.pipeline().addLast(testHandler); - // Sets up a ProbingAction that creates a channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setChannel(channel) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost("") - .build(); - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = existingChannelAction.call(); - //Obtains the outboundMessage passed through pipeline after delay - Object msg = null; - while (msg == null) { - msg = channel.readOutbound(); - } - //tests the passed message is exactly what we expect + //Ensures that we pass in the right message to the channel and haven't marked the future as success yet + Object msg = channel.readOutbound(); assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - assertThat(request).isEqualTo(TEST_MESSAGE); - - // Ensures that we haven't marked future as done until response is received. - assertThat(future.isDone()).isFalse(); + String response = ((ByteBuf) msg).toString(UTF_8); + assertThat(response).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()).isFalse(); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); @@ -121,41 +155,19 @@ public void testBehavior_existingChannel() { @Test public void testSuccess_newChannel() throws Exception { //setup - - LocalAddress address = new LocalAddress(ADDRESS_NAME); - Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); - - // Sets up a Protocol corresponding to when a new connection is created. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - + setupNewChannelProtocol(); + setupNewChannelAction(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - // Sets up a ProbingAction with existing channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.syncUninterruptibly(); + future.sync(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()); + assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java new file mode 100644 index 00000000000..7a713017072 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java @@ -0,0 +1,219 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.TestUtils.TestStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.handlers.ConversionHandler; +import google.registry.monitoring.blackbox.handlers.NettyRule; +import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.junit.Rule; +import org.junit.Test; + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + + /** Used for testing how well probing step can create connection to blackbox server */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + + + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ + private ProbingSequence testSequence; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); + dummyStep = new DummyStep(testProtocol, eventLoopGroup); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(false) + .build(); + } + + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(true) + .build(); + } + + /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ + private void setupSequence() { + testSequence = new ProbingSequence.Builder() + .eventLoopGroup(eventLoopGroup) + .setClass(LocalChannel.class) + .addStep(firstStep) + .makeFirstRepeated() + .addStep(dummyStep) + .build(); + } + + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //there should be no next step + assertThat(firstStep.nextStep()).isNull(); + + //we expect that this exception be thrown + assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); + + } + + @Test + public void testWithSequence_NewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupSequence(); + setupNewChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupSequence(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 46615a506fb..67e2cb7165d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,40 +1,37 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform */ public abstract class TestServer { + private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + this.localAddress = localAddress; + //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override @@ -54,5 +51,35 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** Saves any inbound error as the cause of the promise failure. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 4da75b31c25..ab9997b6c68 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -19,13 +5,11 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -36,10 +20,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - *

It will either redirect the client to the correct location if given the + * It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location

+ * an unexpected host location */ public class WebWhoisServer extends TestServer { @@ -75,14 +59,14 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { + static class RedirectHandler extends ChannelDuplexHandler { private String redirectInput; private String destinationInput; /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; @@ -91,14 +75,15 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { + public void channelRead(ChannelHandlerContext ctx, Object msg) { + HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 50c60d9fc52..8d1722c9625 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,24 +14,47 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { + static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -56,19 +79,102 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain"); + response.headers().set("content-type", "text/plain").set("content-length", "0"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; + } + + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); return response; } + /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ + public static class TestProvider implements Provider { + + private E obj; + + public TestProvider(E obj) { + this.obj = obj; + } + + @Override + public E get() { + return obj; + } + } + + /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ + public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { + + String message; + + public DuplexMessageTest() { + message = ""; + } + + public DuplexMessageTest(String msg) { + message = msg; + } + + @Override + public String toString() { + return message; + } + } + + /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ + public static class TestStep extends ProbingStep { + + public TestStep(Protocol protocol, String testMessage, LocalAddress address) { + super(protocol, new DuplexMessageTest(testMessage)); + this.address = address; + this.duration = Duration.ZERO; + } + } + + /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ + public static class DummyStep extends ProbingStep { + private DefaultPromise future; + + public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { + super(protocol, new DuplexMessageTest()); + future = new DefaultPromise(eventLoopGroup.next()) {}; + duration = Duration.ZERO; + } + + @Override + public void accept(Token token) { + future.setSuccess(token); + } + public DefaultPromise getFuture() { + return future; + } + } + /** Basic outline for {@link Token} instances to be used in tests */ - static abstract class TestToken extends Token { - protected String host; + private static abstract class TestToken extends Token { + private String host; protected TestToken(String host) { this.host = host; @@ -84,7 +190,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String host() { + public String getHost() { return host; } @@ -114,5 +220,33 @@ public Channel channel() { return channel; } } + + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java new file mode 100644 index 00000000000..ef5cba5b60d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -0,0 +1,60 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + */ +@RunWith(JUnit4.class) +public class TokenTest { + + private static String PREFIX = "whois.nic."; + private static String TEST_STARTER = "starter"; + private static String TEST_DOMAIN = "test"; + + public Token webToken = new WebWhoisToken(TEST_DOMAIN); + + @Test + public void testWebToken_MessageModificationSuccess() { + //creates Request message with header + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + message.headers().set("host", TEST_STARTER); + + //attempts to use Token's method for modifying the method based on its stored host + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { + throw new RuntimeException(e); + } + + + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index c9d337d6ad8..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,13 +17,10 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -31,8 +28,8 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 86b54d9a07d..b6b5e8fbe0c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -25,11 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingActionTest; -import google.registry.monitoring.blackbox.ProbingStepTest; -import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -41,6 +41,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -51,8 +52,8 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

+ *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -79,19 +80,16 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { + public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, - ImmutableList.builder().add(handlers).add(echoHandler).build()); + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); } /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - Protocol protocol, - String host, + ProbingAction probingAction, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -111,9 +109,7 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol) - .attr(REMOTE_ADDRESS_KEY, host); - + .attr(PROBING_ACTION_KEY, probingAction); channel = b.connect(localAddress).syncUninterruptibly().channel(); } @@ -122,7 +118,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertReceivedMessage(String message) throws Exception { + public void assertThatCustomWorks(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -163,38 +159,6 @@ ThrowableSubject assertThatClientRootCause() { } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** - * Saves any inbound error as the cause of the promise failure. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 523fb228752..469c62a8f75 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,14 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.ExistingChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; @@ -41,6 +45,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; +import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -62,6 +67,8 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { + private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); + /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -86,12 +93,15 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private final static Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .persistentConnection(false) + .build(); + + private ProbingAction probingAction; private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -103,13 +113,23 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } + private void setupProbingAction(Channel channel) { + probingAction = ExistingChannelAction.builder() + .delay(Duration.ZERO) + .host(SSL_HOST) + .channel(channel) + .outboundMessage(DEFAULT_MESSAGE) + .protocol(PROTOCOL) + .build(); + } + @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - channel.attr(PROTOCOL_KEY).set(PROTOCOL); - channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); + setupProbingAction(channel); + channel.attr(PROBING_ACTION_KEY).set(probingAction); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -140,7 +160,8 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -168,7 +189,8 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -197,7 +219,8 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 95b06e623d1..518bb9ba686 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,7 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -23,18 +22,18 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ - private InboundMessageType receivedMessage; + private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage; + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } - public InboundMessageType getResponse() { + @Override + public String toString() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 63bb2cf5b53..d8a672758da 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,32 +15,44 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; +import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ +/** + * Unit tests for {@link WebWhoisActionHandler}. + * + *

Attempts to test how well {@link WebWhoisActionHandler} works + * when responding to all possible types of responses

+ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; @@ -50,89 +62,96 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; + private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); + private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - + private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; + private ProbingAction probingAction; + private Provider actionHandlerProvider; + private void generateLocalAddress() { + address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + } /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { + private Protocol createProtocol(String name, int port) { return Protocol.builder() .name(name) .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); + .handlerProviders(ImmutableList.of(actionHandlerProvider)) + .persistentConnection(false) + .build(); } /** Initializes new WebWhoisActionHandler */ private void setupActionHandler() { actionHandler = new WebWhoisActionHandler(); + actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); + private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + setupProbingActionBasic( + protocol, + outboundMessage, + makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); + channel.attr(PROBING_ACTION_KEY).set(probingAction); } + private Bootstrap makeBootstrap(EventLoopGroup group) { + return new Bootstrap() + .group(group) + .channel(LocalChannel.class); + } /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() + private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + probingAction = NewChannelAction.builder() .protocol(protocol) .outboundMessage(outboundMessage) .delay(DEFAULT_DURATION) .bootstrap(bootstrap) + .host(TARGET_HOST) + .address(DEFAULT_ADDRESS) .build(); } - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); + private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(host) + .address(address) + .build(); } - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; + private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testSuccess_responseOk() { + public void testBasic_responseOk() throws Exception { //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -140,25 +159,30 @@ public void testSuccess_responseOk() { channel.writeInbound(response); - //assesses that we successfully receivved good response and protocol is unchanged + //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testSuccess_responseBad() { + public void testBasic_responseFailure() { //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseBad", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + FullHttpResponse response = HttpResponseMessage + .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -167,24 +191,63 @@ public void testSuccess_responseBad() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + } + @Test + public void testBasic_responseError() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseError", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + + //stores future + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, and event is success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testSuccess_redirectCloseChannel() { + public void testBasic_redirectCloseChannel() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); + HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", 0); + generateLocalAddress(); + setupChannel(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(outboundMessage); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + //checks that future has not been set to successful or a failure + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); @@ -195,27 +258,69 @@ public void testSuccess_redirectCloseChannel() { } @Test - public void testSuccess_redirectHost() { + public void testBasic_redirectHost() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); channel.writeInbound(originalResponse); + ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); + Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); + assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); + } + + @Test + public void testAdvanced_responseOk() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", TARGET_HOST, group); + //stores future + ChannelFuture future = probingAction.call(); + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + } + + @Test + public void testAdvanced_responseFailure() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", TARGET_HOST, group); + + //stores future + ChannelFuture future = probingAction.call(); + + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } } + From 05696400dbd6b5a05c72ecc8bc026f52df16450d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 195/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 +++++++++----- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/ProbingSequence.java | 1 - .../monitoring/blackbox/ProbingStep.java | 7 +--- .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 - .../monitoring/blackbox/Tokens/Token.java | 4 +- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../monitoring/blackbox/WebWhoisModule.java | 2 +- .../exceptions/EppClientException.java | 29 ------------- .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++- .../handlers/WebWhoisMessageHandler.java | 22 +++++++++- .../blackbox/messages/HttpRequestMessage.java | 41 +++++++++++++------ .../messages/HttpResponseMessage.java | 26 ++++++++---- .../messages/OutboundMessageType.java | 1 - .../blackbox/TestServers/TestServer.java | 16 +++++++- .../blackbox/TestServers/WebWhoisServer.java | 18 +++++++- 19 files changed, 145 insertions(+), 85 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6387207fea4..2eb90a1d6c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -119,4 +119,3 @@ public String toString() { } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 5bad5abf6bf..80b04a3d0c9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.exceptions.EppClientException; import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; import io.netty.channel.local.LocalAddress; -import java.io.IOException; + import java.util.function.Consumer; import org.joda.time.Duration; @@ -164,7 +162,4 @@ public String toString() { message(), parent); } - } - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 24c666b8d9d..61c83de00fd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -120,4 +120,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dba905c0e49..7200a1877e2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -197,4 +197,4 @@ static SslClientInitializer provideSslClientInitializer(SslPro } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 4afc5d95ba7..0acf223eb9e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; @@ -8,6 +22,11 @@ import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; +/** + * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} + * in case of reuse for redirection + */ public class WebWhoisMessageHandler extends MessageHandler { private HttpRequestMessage request; @@ -15,6 +34,7 @@ public class WebWhoisMessageHandler extends MessageHandler { @Inject public WebWhoisMessageHandler() {} + /** Retains {@link HttpRequestMessage} and calls super write method*/ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { request = (HttpRequestMessage) msg; @@ -23,9 +43,9 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) } + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - FullHttpResponse originalResponse = (FullHttpResponse) msg; InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..b06938d80a1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +31,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,16 +38,19 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + + request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + + return finalRequest; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..283b14440ac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,7 +33,7 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); @@ -26,13 +43,8 @@ public static HttpResponseMessage fromResponse(FullHttpResponse response) { else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); return finalResponse; } - - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 0dd17e9d4a9..2d5df10f8c1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType {} - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 67e2cb7165d..a4474b6b8b5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static com.google.common.truth.Truth.assertThat; @@ -20,7 +34,7 @@ import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { private LocalAddress localAddress; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index ab9997b6c68..06b19ea3607 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -20,10 +34,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - * It will either redirect the client to the correct location if given the + *

It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location + * an unexpected host location

*/ public class WebWhoisServer extends TestServer { From 9e01a8bc1a7450bf9def4115fd97b1bbdb4fd1ab Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 196/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 --- .../monitoring/blackbox/NewChannelAction.java | 144 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProberModule.java | 80 ++--- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingSequence.java | 130 ++++----- .../monitoring/blackbox/ProbingStep.java | 147 +++++----- .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/Protocol.java | 78 +---- .../monitoring/blackbox/TokenModule.java | 35 --- .../monitoring/blackbox/Tokens/Token.java | 47 --- .../blackbox/Tokens/WebWhoisToken.java | 54 ---- .../monitoring/blackbox/WebWhoisModule.java | 169 ++++++----- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/ActionHandler.java | 102 +++++-- .../blackbox/handlers/MessageHandler.java | 24 -- .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../handlers/WebWhoisMessageHandler.java | 17 +- .../blackbox/messages/HttpRequestMessage.java | 46 ++- .../messages/HttpResponseMessage.java | 14 +- .../messages/OutboundMessageType.java | 11 +- .../monitoring/blackbox/tokens/Token.java | 20 +- .../blackbox/tokens/WebWhoisToken.java | 32 +- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 32 files changed, 704 insertions(+), 987 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 73bd9127852..0daaf16ded4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,99 +14,59 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; import javax.inject.Singleton; +import org.joda.time.Duration; /** - * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} - * - *

Provides

+ * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores + * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. */ @Module public class ProberModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; + /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + private static final Duration DEFAULT_DURATION = new Duration(4000L); + + /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides - @HttpWhoisProtocol - ProbingSequence provideHttpWhoisSequence( - @HttpWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpsWhoisProtocol - ProbingSequence provideHttpsWhoisSequence( - @HttpsWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return httpWhoIsPort; - } - - @Provides - @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return httpsWhoIsPort; + @Singleton + Duration provideDuration() { + return DEFAULT_DURATION; } + /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - ImmutableMap providePortToProtocolMap( - Set protocolSet) { - return Maps.uniqueIndex(protocolSet, Protocol::port); + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - - + /** Root level {@link Component} that provides each {@link ProbingSequence}. */ @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, - TokenModule.class }) public interface ProberComponent { - @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); - - @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); - - ImmutableMap providePortToProtocolMap(); - - @WebWhoisProtocol Token provideWebWhoisToken(); + //Standard WebWhois sequence + @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2eb90a1d6c3..2dbf48256f9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,108 +14,100 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} - * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ - private EventLoopGroup eventGroup; + /**Each {@link ProbingSequence} requires a start token to begin running. */ + private Token startToken; - /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ - private Bootstrap bootstrap; - - public Bootstrap getBootstrap() { - return bootstrap; - } - - public void start(Token token) { - // calls the first step with input token; - firstStep.accept(token); + public void start() { + // calls the first step with startToken; + firstStep.accept(startToken); } /** - * {@link Builder} which takes in {@link ProbingStep}s - * - * @param Same specified {@code C} for overall {@link ProbingSequence} + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. */ - public static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstSequenceStep; - private EventLoopGroup eventLoopGroup; - private Class classType; - - Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public static class Builder { + + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstRepeatedStep; + private Bootstrap bootstrap; + private Token startToken; + + /** + * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. + * + *

Must be called before adding {@link ProbingStep.Builder}s.

+ */ + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } + + /** Adds start token that activate {@link ProbingSequence}. */ + public Builder addToken(Token token) { + startToken = token; return this; } - Builder addStep(ProbingStep step) { - if (currentStep == null) { + /** + * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * built, and pointed to by the previous {@link ProbingStep} added. + */ + public Builder addStep(ProbingStep.Builder stepBuilder) { + assert (bootstrap != null); + ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + + if (currentStep == null) firstStep = step; - } else { + else currentStep.nextStep(step); - } + currentStep = step; return this; } - /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ - Builder makeFirstRepeated() { - firstSequenceStep = currentStep; - return this; - } - /** Set the class to be the same as {@code C} */ - public Builder setClass(Class classType) { - this.classType = classType; + /** We take special note of the first repeated step. */ + public Builder markFirstRepeated() { + firstRepeatedStep = currentStep; return this; } - public ProbingSequence build() { - currentStep.nextStep(firstSequenceStep); + /** + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and + * calls private constructor to create {@link ProbingSequence}. + */ + public ProbingSequence build() { + if (firstRepeatedStep == null) + firstRepeatedStep = firstStep; + + currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); - return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + return new ProbingSequence(this.firstStep, this.startToken); } - } - /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ - private void setParents() { - ProbingStep currentStep = firstStep.parent(this).nextStep(); - - while (currentStep != firstStep) { - currentStep = currentStep.parent(this).nextStep(); - } - } - private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, - Class classType) { + private ProbingSequence(ProbingStep firstStep, Token startToken) { this.firstStep = firstStep; - this.eventGroup = eventLoopGroup; - this.bootstrap = new Bootstrap() - .group(eventGroup) - .channel(classType); - setParents(); - } - - @Override - public String toString() { - return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); - + this.startToken = startToken; } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 80b04a3d0c9..d54acef325a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,152 +14,145 @@ package google.registry.monitoring.blackbox; +import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.local.LocalAddress; - import java.util.function.Consumer; import org.joda.time.Duration; /** - * Represents generator of actions performed at each step in {@link ProbingSequence} - * - * @param See {@code C} in {@link ProbingSequence} + * {@link AutoValue} class that represents generator of actions performed at each step + * in {@link ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies - * these components on each loop iteration with the consumed {@link Token} and from that, - * generates new {@link ProbingAction} to perform<./p> + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. + * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, + * generates a new {@link ProbingAction} to call.

* - *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -public abstract class ProbingStep implements Consumer { +@AutoValue +public abstract class ProbingStep implements Consumer { - public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); - protected static final Duration DEFAULT_DURATION = new Duration(2000L); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - protected LocalAddress address = DEFAULT_ADDRESS; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ private boolean isLastStep = false; - private ProbingStep nextStep; - private ProbingSequence parent; + private ProbingStep nextStep; - protected Duration duration; + abstract Duration duration(); + abstract Protocol protocol(); + abstract OutboundMessageType messageTemplate(); + abstract Bootstrap bootstrap(); - protected final Protocol protocol; - protected final OutboundMessageType message; - protected ProbingStep(Protocol protocol, OutboundMessageType message) { - this.protocol = protocol; - this.message = message; - } + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder setDuration(Duration value); - private OutboundMessageType message() { - return message; - } + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); - Protocol protocol() { - return protocol; + public abstract ProbingStep build(); } + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - ProbingStep parent(ProbingSequence parent) { - this.parent = parent; - return this; - } - - /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ private ProbingAction generateAction(Token token) throws InternalException { - ProbingAction generatedAction; - - OutboundMessageType message = token.modifyMessage(message()); - - //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction - if (protocol().persistentConnection() && token.channel() != null) { - generatedAction = ExistingChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .channel(token.channel()) - .build(); - } else { - generatedAction = NewChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .bootstrap(parent.getBootstrap()) - .address(address) - .build(); - - } - return generatedAction; + OutboundMessageType message = token.modifyMessage(messageTemplate()); + ProbingAction.Builder probingActionBuilder = ProbingAction.builder() + .setDelay(duration()) + .setProtocol(protocol()) + .setOutboundMessage(message) + .setHost(token.getHost()) + .setBootstrap(bootstrap()); + + if (token.channel() != null) + probingActionBuilder.setChannel(token.channel()); + + return probingActionBuilder.build(); } - /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } @Override public void accept(Token token) { - ProbingAction nextAction; + ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - nextAction = generateAction(token); + currentAction = generateAction(token); } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - //If the next step maintains the connection, pass on the channel from this - if (protocol().persistentConnection()) { - token.channel(nextAction.channel()); - } + //call the created action - ChannelFuture future = nextAction.call(); + ChannelFuture future; + + try { + future = currentAction.call(); + + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Performed"); + nextStep.accept(generateNextToken(token)); + return; + } + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - nextStep.accept(generateNextToken(token)); + //If the next step maintains the connection, pass on the channel from this } else { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + token.setChannel(currentAction.channel()); + + nextStep.accept(generateNextToken(token)); + + }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n" + - "and parent sequence: %s", + "OutboundMessage: %s\n", protocol(), - message(), - parent); + messageTemplate().getClass().getName()); } + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 61c83de00fd..b0342c74b7d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,95 +16,43 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; +import io.netty.util.AttributeKey; import javax.inject.Provider; /** - * Protocol Class packages all static variables necessary for a certain type of connection - * Both the host and the path can be changed for the same protocol - * Mainly packages the handlers necessary for the requisite channel pipeline + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. */ @AutoValue public abstract class Protocol { - public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - - /** - * Default names associated with each protocol - */ - final static String EPP_PROTOCOL_NAME = "EPP"; - final static String DNS_PROTOCOL_NAME = "DNS"; - final static String WHOIS_PROTOCOL_NAME = "WHOIS"; - final static String RDAP_PROTOCOL_NAME = "RDAP"; - - private String host; - private String path = ""; - private ProbingAction probingAction; - - /** Setter method for Protocol's host*/ - public Protocol host(String host) { - this.host = host; - return this; - } - - /** Getter method for Protocol's host*/ - public String host() { - return host; - } - - /** Setter method for Protocol's path*/ - public Protocol path(String path) { - this.path = path; - return this; - } - - /** Getter method for Protocol's path*/ - public String path() { - return path; - } - - /** Setter method for Protocol's ProbingAction parent*/ - public Protocol probingAction(ProbingAction probingAction) { - this.probingAction = probingAction; - return this; - } - - /** Getter method for Protocol's path*/ - public ProbingAction probingAction() { - return probingAction; - } - - /** If connection associated with Protocol is persistent, which is only EPP */ - public boolean persistentConnection() { - return name() == EPP_PROTOCOL_NAME; - } + /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - /** Protocol Name */ - public abstract String name(); + abstract String name(); - /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - public abstract ImmutableList> handlerProviders(); + abstract ImmutableList> handlerProviders(); - - public abstract Builder toBuilder(); + /** Boolean that notes if connection associated with Protocol is persistent.*/ + abstract boolean persistentConnection(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } - /** Builder for {@link Protocol}. */ @AutoValue.Builder public abstract static class Builder { - public abstract Builder name(String value); + public abstract Builder setName(String value); + + public abstract Builder setPort(int num); - public abstract Builder port(int num); + public abstract Builder setHandlerProviders(ImmutableList> providers); - public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder setPersistentConnection(boolean value); public abstract Protocol build(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 7200a1877e2..dcc9635beaa 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,62 +17,86 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; -import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandler; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - final static String DOMAIN_SUFFIX = "whois.nic."; + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + private static final String DOMAIN_PREFIX = "whois.nic."; + + /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + private static final int maximumMessageLengthBytes = 512 * 1024; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - - - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - - + /** {@link Provides} standard WebWhois sequence. */ @Provides - @HttpWhoisProtocol - static ProbingStep provideHttpWhoisProbingSequence( - @HttpWhoisProtocol Protocol httpWhoisProtocol) { - return new ProbingStepWeb<>(httpWhoisProtocol); + @WebWhoisProtocol + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, + WebWhoisToken webWhoisToken, + @WebWhoisProtocol Bootstrap bootstrap) { + + return new ProbingSequence.Builder() + .addToken(webWhoisToken) + .setBootstrap(bootstrap) + .addStep(probingStepBuilder) + .build(); } + + /** {@link Provides} only step used in WebWhois sequence. */ @Provides - @HttpsWhoisProtocol - static ProbingStep provideHttpsWhoisProbingStep( - @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { - return new ProbingStepWeb<>(httpsWhoisProtocol); + @WebWhoisProtocol + static ProbingStep.Builder provideWebWhoisStepBuilder( + @HttpWhoisProtocol Protocol httpWhoisProtocol, + HttpRequestMessage messageTemplate, + Duration duration) { + + return ProbingStep.builder() + .setProtocol(httpWhoisProtocol) + .setMessageTemplate(messageTemplate) + .setDuration(duration); } - + /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides @HttpWhoisProtocol @@ -80,28 +104,14 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpProtocolForSet( - @HttpWhoisProtocol int httpWhoisPort, - @HttpWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTP_PROTOCOL_NAME) + .setPort(httpWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } - + /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ @Singleton @Provides @HttpsWhoisProtocol @@ -109,40 +119,28 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpsProtocolForSet( - @HttpsWhoisProtocol int httpsWhoisPort, - @HttpsWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTPS_PROTOCOL_NAME) + .setPort(httpsWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } + /** {@link Provides} the prefix where we probe: "prefix.tld". */ @Provides - @WebWhoisProtocol - String provideHttpWhoisHost() { - return "app"; + @Named("Web-WHOIS-Prefix") + String provideWhoisPrefix() { + return DOMAIN_PREFIX; } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -151,13 +149,14 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -167,33 +166,57 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } + @Provides + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); + } + + @Provides + static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { + return new HttpObjectAggregator(maxContentLength); + } + + /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + @Provides + @HttpsWhoisProtocol + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); + } + /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + @Singleton @Provides @WebWhoisProtocol - static MessageHandler provideMessageHandler() { - return new WebWhoisMessageHandler(); + static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + return new Bootstrap() + .group(eventLoopGroup) + .channel(NioSocketChannel.class); } @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); + @WebWhoisProtocol + int provideMaximumMessageLengthBytes() { + return maximumMessageLengthBytes; } + /** {@link Provides} the list of top level domains to be probed */ + @Singleton @Provides - static HttpObjectAggregator provideHttpObjectAggregator() { - return new HttpObjectAggregator(1048576); + @WebWhoisProtocol + ImmutableList provideTopLevelDomains() { + return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); } @Provides - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index adb833ec629..be3d725c833 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,10 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when - * the action performed failed due to an issue in the connection with the server. + * Base exception class for all instances when the status of the action performed is ERROR. */ -public class ConnectionException extends UndeterminedStateException { +public class ConnectionException extends Exception { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 7898203e92d..e397393b4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,10 +14,11 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; @@ -26,16 +27,18 @@ import io.netty.channel.ChannelPromise; /** - *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} - * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception - * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses - * specify further work to be done for specific kinds of channel pipelines.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed + * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} + * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * + *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -47,28 +50,42 @@ public enum ResponseType {SUCCESS, FAILURE, ERROR} /** Status of response for current {@link ActionHandler} instance */ private static ResponseType status; + /** {@link ChannelPromise} that informs {@link google.registry.monitoring.blackbox.ProbingAction} if response has been received. */ protected ChannelPromise finished; - /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** Returns initialized {@link ChannelPromise} to {@link google.registry.monitoring.blackbox.ProbingAction}.*/ public ChannelFuture getFuture() { return finished; } - /** Initializes new {@link ChannelPromise} */ + /** Initializes the same {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } + /** Initializes the same {@link ChannelPromise} in case current channel is reused (usually for EPP).*/ + public void resetFuture() { + finished = finished.channel().newPromise(); + } + + /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { - //simply marks finished as success + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { + status = ResponseType.SUCCESS; - finished.setSuccess(); + + if (!finished.isSuccess()) { + finished.setSuccess(); + } } - /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ + /** + * Logs the channel and pipeline that caused error, closes channel, then informs + * {@link google.registry.monitoring.blackbox.ProbingAction} listeners of error. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).log(String.format( @@ -76,27 +93,62 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.channel().toString(), ctx.channel().pipeline().toString())); - - if (ResponseException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + if (cause instanceof ResponseException) { + //On ResponseException, we know the response is a failure. As a result, + //we set the status to FAILURE, then inform the MetricsHandler of this status = ResponseType.FAILURE; + + //Since it wasn't a success, we still want to log to see what caused the FAILURE logger.atInfo().log(cause.getMessage()); + + //As always, inform the ProbingStep that we successfully completed this action finished.setSuccess(); - } else if (ServerSideException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + + } else if (cause instanceof ConnectionException) { + //On ConnectionException, we know the response type is an error. As a result, + //we set the status to ERROR, then inform the MetricsHandler of this status = ResponseType.ERROR; + + //Since it wasn't a success, we still log what caused the ERROR logger.atInfo().log(cause.getMessage()); finished.setSuccess(); - } else if (InternalException.class.isInstance(cause)){ + + //As this was an ERROR in the connection, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + } else if (cause instanceof InternalException){ + //For an internal error, metrics should not be collected, so we log what caused this, and + //inform the ProbingStep the Prober had an internal error on this action logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); + + + //As this was an internal error, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } else { - finished.setFailure(cause); + //In the case of any other kind of error, we assume it is some type of connection ERROR, + //so we treat it as such: + + status = ResponseType.ERROR; + + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - //due to failure, close channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + + } + + /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ + @VisibleForTesting + ResponseType getStatus() { + return status; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index ac844ac99df..919006592ea 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -89,8 +90,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); - Protocol protocol = action.protocol(); + Protocol protocol = channel.attr(PROTOCOL_KEY).get(); + String host = channel.attr(REMOTE_ADDRESS_KEY).get(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -103,7 +104,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), action.host(), protocol.port()); + .newHandler(channel.alloc(), host, protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 0acf223eb9e..58c395ad86e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -17,37 +17,36 @@ import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; /** - * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection + * in case of reuse for redirection. */ -public class WebWhoisMessageHandler extends MessageHandler { - - private HttpRequestMessage request; +public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method*/ + /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - request = (HttpRequestMessage) msg; + HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; - InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); + HttpResponseMessage response = new HttpResponseMessage(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b06938d80a1..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,19 +19,30 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); @@ -39,18 +50,29 @@ public HttpRequestMessage setUri(String path) { } /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; - ByteBuf buf = request.content(); + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; - request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + } else { + throw new IllegalArgumentException(); + } + } - return finalRequest; + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 283b14440ac..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -34,17 +34,9 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 2d5df10f8c1..be6c872cc3e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,16 @@ package google.registry.monitoring.blackbox.messages; +import google.registry.monitoring.blackbox.exceptions.InternalException; + /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType {} +public interface OutboundMessageType { + + /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + public OutboundMessageType modifyMessage(String... args) throws InternalException; + + /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + public String name(); +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dab5851e8d8..dd1882b5686 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,18 +14,16 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.ProbingSequence; -import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} - * in a single loop of a {@link ProbingSequence}. + * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} + * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes + * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -33,21 +31,17 @@ */ public abstract class Token { - /** - * {@link Channel} that always starts out as null. Once a persistent connection - * is made (such as EPP), that channel is stored in the token and passed on to - * later steps in the sequence until a new loop begins. - */ + /** {@link Channel} that always starts out as null. */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String host(); + public abstract String getHost(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index bb06ee89db6..2847e5ce0eb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; -import java.util.LinkedList; +import java.util.List; import javax.inject.Inject; import javax.inject.Named; @@ -33,38 +33,42 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final static String PREFIX = "whois.nic."; + private final String prefix; /** {@link ImmutableList} of all top level domains to be probed. */ - private final Iterator topLevelDomainsIterator; + private final ImmutableList topLevelDomains; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private String currentDomain; + private int domainsIndex; @Inject - public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken( + @Named("Web-WHOIS-Prefix") String prefix, + @WebWhoisProtocol ImmutableList topLevelDomains) { - topLevelDomainsIterator = topLevelDomains.iterator(); - currentDomain = topLevelDomainsIterator.next(); + domainsIndex = 0; + this.prefix = prefix; + this.topLevelDomains = topLevelDomains; } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + domainsIndex += 1; + domainsIndex %= topLevelDomains.size(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { - return original.modifyMessage(host()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { + return original.modifyMessage(getHost()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String host() { - return PREFIX + currentDomain; + public String getHost() { + return prefix + topLevelDomains.get(domainsIndex); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Mon, 29 Jul 2019 12:04:58 -0400 Subject: [PATCH 197/337] Minor Style Fixes --- .../monitoring/blackbox/ProbingAction.java | 85 ++++++++++--------- .../monitoring/blackbox/ProbingStep.java | 8 +- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..3f6a962b12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -89,11 +90,47 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** The {@link SocketAddress} instance that specifies remote address of connection */ + @Nullable public abstract SocketAddress address(); /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ public abstract Optional bootstrap(); + + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> actionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** * The method that performs the work of the actual action. * @@ -130,41 +167,13 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } @@ -224,7 +233,7 @@ public abstract static class Builder { abstract Channel channel(); - abstract Optional address(); + abstract SocketAddress address(); abstract Optional bootstrap(); @@ -233,7 +242,7 @@ public abstract static class Builder { abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) + if (address() == null) //If no address has been supplied, we set it based on the host and port setAddress(new InetSocketAddress(host(), protocol().port())); @@ -259,7 +268,7 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap().get().connect(address()); setChannel(connectionFuture.channel()); setConnectionFuture(connectionFuture); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index d54acef325a..47c89c72c11 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -21,7 +21,9 @@ import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import java.net.SocketAddress; import java.util.function.Consumer; +import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -48,6 +50,7 @@ public abstract class ProbingStep implements Consumer { abstract Protocol protocol(); abstract OutboundMessageType messageTemplate(); abstract Bootstrap bootstrap(); + @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -60,6 +63,8 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); + public abstract Builder setAddress(SocketAddress address); + public abstract ProbingStep build(); } @@ -87,7 +92,8 @@ private ProbingAction generateAction(Token token) throws InternalException { .setProtocol(protocol()) .setOutboundMessage(message) .setHost(token.getHost()) - .setBootstrap(bootstrap()); + .setBootstrap(bootstrap()) + .setAddress(address()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); From 7778d34221f1898fe672f1fa6ab852bf78f2180f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:05:59 -0400 Subject: [PATCH 198/337] Updated build.gradle file --- prober/build.gradle | 3 - .../blackbox/ProbingSequenceStepTest.java | 219 ------------------ .../blackbox/ProbingSequenceTest.java | 96 -------- .../monitoring/blackbox/ProbingStepTest.java | 196 ++++++++-------- 4 files changed, 102 insertions(+), 412 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java diff --git a/prober/build.gradle b/prober/build.gradle index e48eacb8bf9..26d44c0a465 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,8 +16,6 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - - dependencies { def deps = rootProject.dependencyMap @@ -46,7 +44,6 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java deleted file mode 100644 index 7a713017072..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.TestUtils.TestStep; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.handlers.ConversionHandler; -import google.registry.monitoring.blackbox.handlers.NettyRule; -import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; -import org.junit.Rule; -import org.junit.Test; - -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { - - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ - private ProbingSequence testSequence; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); - dummyStep = new DummyStep(testProtocol, eventLoopGroup); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(false) - .build(); - } - - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(true) - .build(); - } - - /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ - private void setupSequence() { - testSequence = new ProbingSequence.Builder() - .eventLoopGroup(eventLoopGroup) - .setClass(LocalChannel.class) - .addStep(firstStep) - .makeFirstRepeated() - .addStep(dummyStep) - .build(); - } - - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.nextStep()).isNull(); - - //we expect that this exception be thrown - assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); - - } - - @Test - public void testWithSequence_NewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupSequence(); - setupNewChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupSequence(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 5c4452df7b3..2b0559514a2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,101 +1,5 @@ -// Copyright 2019 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.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doCallRealMethod; - -import google.registry.monitoring.blackbox.tokens.Token; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) public class ProbingSequenceTest { - - private ProbingStep setupMock() { - ProbingStep mock = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(mock).nextStep(); - return mock; - } - - private static class Wrapper { - - T data; - - public Wrapper(T data) { - this.data = data; - } - } - - @Test - public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(firstStep) - .addStep(secondStep) - .addStep(thirdStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(thirdStep); - assertThat(thirdStep.nextStep()).isEqualTo(firstStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - - @Test - public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(thirdStep) - .addStep(secondStep) - .markFirstRepeated() - .addStep(firstStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(firstStep); - assertThat(thirdStep.nextStep()).isEqualTo(secondStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 1f09dd13553..090753014e4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,59 +11,57 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.TestUtils.dummyStep; +import static google.registry.monitoring.blackbox.TestUtils.testStep; +import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; -import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; -import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingStepTest { +public class ProbingSequenceStepTest { /** Basic Constants necessary for tests */ - private final static String ADDRESS_NAME = "TEST_ADDRESS"; - private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final static int PROTOCOL_PORT = 0; - private final static String TEST_MESSAGE = "TEST_MESSAGE"; - private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -74,106 +72,117 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** - * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} - * is called, it just marks the supplied future as succeeded, returning the requisite token. - */ - private ProbingStep dummyStep() { - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(dummyStep).nextStep(); - return dummyStep; + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); } + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } - @Test - public void testNewChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); + dummyStep = dummyStep(eventLoopGroup); - // Sets up Protocol for when we create a new channel. - Protocol testProtocol = Protocol.builder() + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); + } - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) .build(); + } - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); + //there should be no next step + assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); - //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(address); + } + + @Test + public void testNewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //checks that we have appropriately sent the write message to server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - verify(dummyStep, times(1)).accept(any(Token.class)); + assertThat(future.get()).isEqualTo(testToken); + } - @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - - // Sets up Protocol for when a channel already exists. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) - .build(); - - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) - .build(); - - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); - - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - - //Assures that the channel has a succeeded connectionFuture. - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, ""); + //setup + setupExistingProtocol(); + setupSteps(); + setupChannel(); + setupExistingChannelToken(); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -182,21 +191,20 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); - Object msg = channel.readOutbound(); - - while (msg == null) { - msg = channel.readOutbound(); - } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked - // as a success - verify(dummyStep, times(1)).accept(any(Token.class)); + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); } } From 6c6052ac49824f4751b250009214bfec21889243 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 199/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From dd523cd5cc8617eb6ef1487175ebb4c1d700c142 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:54:13 -0400 Subject: [PATCH 200/337] Updated WebWhois tests. --- .../blackbox/ProbingActionTest.java | 56 +++--- .../blackbox/ProbingSequenceTest.java | 183 ++++++++++++++++++ .../monitoring/blackbox/ProbingStepTest.java | 3 +- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 93 +++++++-- .../monitoring/blackbox/TokenTest.java | 13 +- .../blackbox/handlers/ConversionHandler.java | 2 +- .../blackbox/handlers/NettyRule.java | 12 +- .../handlers/SslClientInitializerTest.java | 46 ++--- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 159 ++++++++------- 11 files changed, 422 insertions(+), 157 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index cbcf2fc82b0..162044c2036 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -83,31 +84,31 @@ public class ProbingActionTest { /** Sets up a {@link Protocol} corresponding to when a new connection is created */ private void setupNewChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(false) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) .build(); } /** Sets up a {@link Protocol} corresponding to when a new connection exists */ private void setupExistingChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(true) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(true) .build(); } - /** Sets up a {@link NewChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ private void setupNewChannelAction() { - newChannelAction = NewChannelAction.builder() - .bootstrap(bootstrap) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") - .address(address) + newChannelAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") + .setAddress(address) .build(); } @@ -115,25 +116,25 @@ private void setupChannel() { channel = new EmbeddedChannel(); } - /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ExistingChannelAction.builder() - .channel(channel) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") + existingChannelAction = ProbingAction.builder() + .setChannel(channel) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") .build(); } @Test - public void testBehavior_existingChannel() { + public void testBehavior_existingChannel() throws InternalException { //setup setupChannel(); setupExistingChannelProtocol(); - setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); + setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -147,6 +148,7 @@ public void testBehavior_existingChannel() { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -156,9 +158,9 @@ public void testBehavior_existingChannel() { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - setupNewChannelAction(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + setupNewChannelAction(); ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2b0559514a2..681a5346d55 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,5 +1,188 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; + +import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; +import java.net.SocketAddress; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) public class ProbingSequenceTest { + private final static String TEST_HOST = "TEST_HOST"; + + + private Bootstrap dummyBootstrap = new Bootstrap(); + private Token testToken = new ProbingSequenceTestToken(); + + /** + * Custom {@link ProbingStep} subclass that acts as a mock + * step, so we can test how well {@link ProbingSequence} builds + * a linked list of {@link ProbingStep}s from their {@link Builder}s. + */ + private static class TestStep extends ProbingStep { + private Bootstrap bootstrap; + private String marker; + + /** We implement all abstract methods to simply return null, as we have no use for them here. */ + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + SocketAddress address() { + return null; + } + + /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + /** + * Builder for {@link TestStep}, that extends {@link ProbingStep.Builder} so that these can be + * input into the {@link ProbingSequence.Builder}. + */ + public static class Builder extends ProbingStep.Builder { + /** We test to see if we accurately add the right bootstrap to all {@link ProbingStep}s/ */ + private Bootstrap bootstrap; + + /** We also mark each step in order to ensure that when running, they are arranged in the right order. */ + private String marker; + + @Override + public ProbingStep.Builder setDuration(Duration value) { + return this; + } + + @Override + public ProbingStep.Builder setProtocol(Protocol value) { + return this; + } + + @Override + public ProbingStep.Builder setMessageTemplate(OutboundMessageType value) { + return null; + } + + @Override + public ProbingStep.Builder setAddress(SocketAddress address) { + return null; + } + + @Override + public ProbingStep.Builder setBootstrap(Bootstrap value) { + bootstrap = value; + return this; + } + + public ProbingStep.Builder addMarker(String value) { + marker = value; + return this; + } + + @Override + public ProbingStep build() { + return new TestStep(bootstrap, marker); + } + } + private TestStep(Bootstrap bootstrap, String marker) { + this.bootstrap = bootstrap; + this.marker = marker; + } + + /** + * On a call to accept, we modify the token to reflect what the current step is, so we can get + * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated + * in order. + */ + @Override + public void accept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + if (!isLastStep) { + nextStep().accept(token); + } else { + ((TestStep)nextStep()).specialAccept(token); + } + } + + /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ + public void specialAccept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + return; + } + } + + @Test + public void testSequenceBasicConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("firstsecondthirdfirst"); + } + + @Test + public void testSequenceAdvancedConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(thirdStepBuilder) + .addStep(secondStepBuilder) + .markFirstRepeated() + .addStep(firstStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("thirdsecondfirstsecond"); + } + @Test + public void testSequenceConstruction_Failure() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + assertThrows(AssertionError.class, () -> { + ProbingSequence sequence = new ProbingSequence.Builder() + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .setBootstrap(dummyBootstrap) + .build(); + }); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 090753014e4..ee38e7cdf74 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -21,7 +21,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; @@ -47,7 +46,7 @@ import org.junit.Test; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { +public class ProbingStepTest { /** Basic Constants necessary for tests */ private final String ADDRESS_NAME = "TEST_ADDRESS"; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 06b19ea3607..337d755e971 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -93,11 +93,11 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 8d1722c9625..161304c1f04 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,9 +17,11 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -37,6 +39,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; +import java.net.Socket; +import java.net.SocketAddress; +import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -141,26 +146,67 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } + + @Override + public OutboundMessageType modifyMessage(String... args) throws InternalException { + message = args[0]; + return this; + } + + @Override + public String name() { + return "Test Message of: " + this.toString(); + } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static class TestStep extends ProbingStep { + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .setAddress(address) + .build(); - public TestStep(Protocol protocol, String testMessage, LocalAddress address) { - super(protocol, new DuplexMessageTest(testMessage)); - this.address = address; - this.duration = Duration.ZERO; - } + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { - super(protocol, new DuplexMessageTest()); - future = new DefaultPromise(eventLoopGroup.next()) {}; - duration = Duration.ZERO; + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; + } + + @Nullable + @Override + SocketAddress address() { + return null; } @Override @@ -170,11 +216,16 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } + + @Override + public String toString() { + return "Dummy Step"; + } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - private String host; + protected String host; protected TestToken(String host) { this.host = host; @@ -221,6 +272,22 @@ public Channel channel() { } } + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..67963805733 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,10 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; @@ -34,20 +35,20 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..a8506a996a9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -37,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b6b5e8fbe0c..b38c1911940 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; @@ -89,7 +90,8 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - ProbingAction probingAction, + Protocol protocol, + String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -109,7 +111,9 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROBING_ACTION_KEY, probingAction); + .attr(PROTOCOL_KEY, protocol) + .attr(REMOTE_ADDRESS_KEY, host); + channel = b.connect(localAddress).syncUninterruptibly().channel(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 469c62a8f75..83c8e132f07 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,17 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ExistingChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; @@ -45,7 +46,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; -import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,8 +67,6 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); - /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -93,15 +91,12 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .persistentConnection(false) - .build(); - - private ProbingAction probingAction; + private final static Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -113,23 +108,13 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } - private void setupProbingAction(Channel channel) { - probingAction = ExistingChannelAction.builder() - .delay(Duration.ZERO) - .host(SSL_HOST) - .channel(channel) - .outboundMessage(DEFAULT_MESSAGE) - .protocol(PROTOCOL) - .build(); - } - @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - setupProbingAction(channel); - channel.attr(PROBING_ACTION_KEY).set(probingAction); + channel.attr(PROTOCOL_KEY).set(PROTOCOL); + channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -160,8 +145,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -189,8 +173,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -219,8 +202,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 518bb9ba686..e170fad8b8c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox.handlers; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index d8a672758da..72d5d5078df 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,21 +15,21 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; @@ -65,6 +65,14 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); + private static final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of()) + .setName("test_protocol") + .setPersistentConnection(false) + .setPort(HTTPS_PORT) + .build(); + private LocalAddress address; private EmbeddedChannel channel; @@ -75,30 +83,38 @@ public class WebWhoisActionHandlerTest { private void generateLocalAddress() { address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); } + /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port) { + private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of(actionHandlerProvider)) - .persistentConnection(false) + .setName(name) + .setPort(port) + .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) + .setPersistentConnection(persistentConnection) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); + private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { + actionHandler = new WebWhoisActionHandler( + bootstrap, + STANDARD_PROTOCOL, + STANDARD_PROTOCOL, + messageTemplate, + 80, + 443 + ); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); setupProbingActionBasic( protocol, outboundMessage, makeBootstrap(new NioEventLoopGroup(1))); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROBING_ACTION_KEY).set(probingAction); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -108,24 +124,25 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { } /**Sets up probingAction for when testing redirection */ private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(TARGET_HOST) - .address(DEFAULT_ADDRESS) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(TARGET_HOST) + .setAddress(DEFAULT_ADDRESS) + .setChannel(channel) .build(); } private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(host) - .address(address) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(host) + .setAddress(address) .build(); } @@ -136,10 +153,13 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, true); generateLocalAddress(); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + + setupChannel(initialProtocol, msg); //stores future @@ -151,7 +171,7 @@ public void testBasic_responseOk() throws Exception { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -161,15 +181,16 @@ public void testBasic_responseOk() throws Exception { //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseBad", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseBad", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -181,8 +202,7 @@ public void testBasic_responseFailure() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage - .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -194,14 +214,15 @@ public void testBasic_responseFailure() { assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseError() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseError", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseError", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -213,7 +234,7 @@ public void testBasic_responseError() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -224,27 +245,30 @@ public void testBasic_responseError() { assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_redirectCloseChannel() { //setup - HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", 0); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", 0, true); generateLocalAddress(); - setupChannel(initialProtocol, outboundMessage); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(outboundMessage); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -260,12 +284,15 @@ public void testBasic_redirectCloseChannel() { @Test public void testBasic_redirectHost() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); generateLocalAddress(); setupChannel(initialProtocol, msg); - HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); //store future @@ -275,27 +302,24 @@ public void testBasic_redirectHost() { channel.writeInbound(originalResponse); - ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - //gets changed protocol - Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); - assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); } @Test - public void testAdvanced_responseOk() { + public void testAdvanced_responseOk() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); //stores future ChannelFuture future = probingAction.call(); @@ -305,15 +329,16 @@ public void testAdvanced_responseOk() { } @Test - public void testAdvanced_responseFailure() { + public void testAdvanced_responseFailure() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); //stores future ChannelFuture future = probingAction.call(); From 599fea0cf0b6fb13c5f3d0ee054e1752cc5b556f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 201/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- prober/.gitignore | 2 +- .../registry/monitoring/blackbox/Prober.java | 9 +- .../monitoring/blackbox/ProberModule.java | 15 ++- .../monitoring/blackbox/ProbingAction.java | 96 +++++++-------- .../monitoring/blackbox/ProbingSequence.java | 24 +--- .../monitoring/blackbox/ProbingStep.java | 55 ++++++--- .../monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 49 ++++---- .../exceptions/ConnectionException.java | 5 +- .../blackbox/exceptions/FailureException.java | 15 ++- .../exceptions/InternalException.java | 30 ----- .../exceptions/ResponseException.java | 29 ----- .../blackbox/handlers/ActionHandler.java | 94 +++------------ .../handlers/WebWhoisActionHandler.java | 51 ++++---- .../blackbox/messages/HttpRequestMessage.java | 4 +- .../messages/HttpResponseMessage.java | 6 +- .../messages/OutboundMessageType.java | 7 +- .../monitoring/blackbox/tokens/Token.java | 20 +-- .../blackbox/tokens/WebWhoisToken.java | 32 +++-- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../blackbox/ProbingActionTest.java | 9 +- .../blackbox/ProbingSequenceTest.java | 114 +++--------------- .../monitoring/blackbox/ProbingStepTest.java | 4 +- .../monitoring/blackbox/TestUtils.java | 21 +--- .../monitoring/blackbox/TokenTest.java | 8 +- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 106 +++++----------- 31 files changed, 291 insertions(+), 526 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/.gitignore b/prober/.gitignore index c86568e7672..77b1e2de2de 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..307afd34d81 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +29,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 0daaf16ded4..1db97d1b581 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,14 +14,18 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.Set; import javax.inject.Singleton; import org.joda.time.Duration; @@ -33,7 +37,7 @@ public class ProberModule { /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = new Duration(4000L); + private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @@ -42,6 +46,12 @@ EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + @Provides + @Singleton + Class provideChannelClass() { + return NioSocketChannel.class; + } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides @Singleton @@ -51,6 +61,7 @@ Duration provideDuration() { /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides + @Singleton static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; @@ -66,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); + Set provideAllSequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 3f6a962b12d..67494dd5f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,25 +14,29 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -65,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -80,31 +87,18 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - @Nullable - public abstract SocketAddress address(); - - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { // Write appropriate outboundMessage to pipeline ChannelFuture channelFuture = actionHandler.getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> actionHandler.resetFuture(), - //inform ProbingStep of the status of our action future -> { if (future.isSuccess()) @@ -141,7 +135,7 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -154,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -180,19 +174,24 @@ public ChannelFuture performAction() throws InternalException { /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -210,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -221,40 +226,30 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract SocketAddress address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (address() == null) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + System.out.println("test"); + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -268,14 +263,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -293,7 +285,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2dbf48256f9..91c4165c068 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -49,32 +49,18 @@ public static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; private ProbingStep firstRepeatedStep; - private Bootstrap bootstrap; - private Token startToken; - /** - * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. - * - *

Must be called before adding {@link ProbingStep.Builder}s.

- */ - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } + private Token startToken; - /** Adds start token that activate {@link ProbingSequence}. */ - public Builder addToken(Token token) { - startToken = token; - return this; + public Builder(Token startToken) { + this.startToken = startToken; } /** - * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, * built, and pointed to by the previous {@link ProbingStep} added. */ - public Builder addStep(ProbingStep.Builder stepBuilder) { - assert (bootstrap != null); - ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + public Builder addStep(ProbingStep step) { if (currentStep == null) firstStep = step; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 47c89c72c11..ca980100067 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import java.net.SocketAddress; import java.util.function.Consumer; -import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -39,18 +37,23 @@ @AutoValue public abstract class ProbingStep implements Consumer { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ - private boolean isLastStep = false; + protected boolean isLastStep = false; private ProbingStep nextStep; + /** Time delay duration between actions. */ abstract Duration duration(); + + /** {@link Protocol} type for this step. */ abstract Protocol protocol(); + + /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ abstract OutboundMessageType messageTemplate(); + + /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ abstract Bootstrap bootstrap(); - @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -63,8 +66,6 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); - public abstract Builder setAddress(SocketAddress address); - public abstract ProbingStep build(); } @@ -85,18 +86,18 @@ ProbingStep nextStep() { } /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws InternalException { + private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) .setProtocol(protocol()) .setOutboundMessage(message) - .setHost(token.getHost()) - .setBootstrap(bootstrap()) - .setAddress(address()); + .setHost(token.host()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); + else + probingActionBuilder.setBootstrap(bootstrap()); return probingActionBuilder.build(); } @@ -107,44 +108,58 @@ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } + /** + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. + * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

+ */ @Override public void accept(Token token) { ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - //call the created action ChannelFuture future; - try { + //call the generated action future = currentAction.call(); - - } catch(InternalException e) { + } catch(UndeterminedStateException e) { + //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); + + //Move on to next step in ProbingSequence nextStep.accept(generateNextToken(token)); return; } - //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - //If the next step maintains the connection, pass on the channel from this + } else { + //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index b0342c74b7d..92470ef62c8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -29,7 +29,7 @@ public abstract class Protocol { /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - abstract String name(); + public abstract String name(); public abstract int port(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dcc9635beaa..c5e41fea38b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,6 +18,7 @@ import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,6 +27,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; @@ -44,11 +46,10 @@ @Module public class WebWhoisModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - private static final String DOMAIN_PREFIX = "whois.nic."; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; + private static final String HTTP_PROTOCOL_NAME = "http"; + private static final String HTTPS_PROTOCOL_NAME = "https"; /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; @@ -68,16 +69,14 @@ public class WebWhoisModule { /** {@link Provides} standard WebWhois sequence. */ @Provides - @WebWhoisProtocol + @Singleton + @IntoSet ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, - WebWhoisToken webWhoisToken, - @WebWhoisProtocol Bootstrap bootstrap) { + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { - return new ProbingSequence.Builder() - .addToken(webWhoisToken) - .setBootstrap(bootstrap) - .addStep(probingStepBuilder) + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) .build(); } @@ -85,15 +84,18 @@ ProbingSequence provideWebWhoisSequence( /** {@link Provides} only step used in WebWhois sequence. */ @Provides @WebWhoisProtocol - static ProbingStep.Builder provideWebWhoisStepBuilder( + static ProbingStep provideWebWhoisStep( @HttpWhoisProtocol Protocol httpWhoisProtocol, + @WebWhoisProtocol Bootstrap bootstrap, HttpRequestMessage messageTemplate, Duration duration) { return ProbingStep.builder() .setProtocol(httpWhoisProtocol) + .setBootstrap(bootstrap) .setMessageTemplate(messageTemplate) - .setDuration(duration); + .setDuration(duration) + .build(); } /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @@ -126,13 +128,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** {@link Provides} the prefix where we probe: "prefix.tld". */ - @Provides - @Named("Web-WHOIS-Prefix") - String provideWhoisPrefix() { - return DOMAIN_PREFIX; - } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @@ -187,10 +182,12 @@ static SslClientInitializer provideSslClientInitializer(SslPro @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + static Bootstrap provideBootstrap( + EventLoopGroup eventLoopGroup, + Class channelClass){ return new Bootstrap() .group(eventLoopGroup) - .channel(NioSocketChannel.class); + .channel(channelClass); } @Provides @@ -210,13 +207,13 @@ ImmutableList provideTopLevelDomains() { @Provides @HttpWhoisProtocol int provideHttpWhoisPort() { - return httpWhoIsPort; + return HTTP_WHOIS_PORT; } @Provides @HttpsWhoisProtocol int provideHttpsWhoisPort() { - return httpsWhoIsPort; + return HTTPS_WHOIS_PORT; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index be3d725c833..adb833ec629 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,9 +15,10 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is ERROR. + * Subclass of {@link UndeterminedStateException} that represents all instances when + * the action performed failed due to an issue in the connection with the server. */ -public class ConnectionException extends Exception { +public class ConnectionException extends UndeterminedStateException { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 9f716bb2589..36687e7ac82 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,5 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.exceptions; +/** + * Base exception class for all instances when the status of the action performed is FAILURE. + */ +public class FailureException extends Exception { + + public FailureException(String msg) { + super(msg); + } + + public FailureException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index e397393b4e9..0c9e93cc6dd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,13 +14,11 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -33,7 +31,7 @@ * messages that implement the {@link InboundMessageType} interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

@@ -44,111 +42,59 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); - - } else if (cause instanceof InternalException){ - //For an internal error, metrics should not be collected, so we log what caused this, and - //inform the ProbingStep the Prober had an internal error on this action - logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - - //As this was an internal error, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } else { - //In the case of any other kind of error, we assume it is some type of connection ERROR, - //so we treat it as such: + //On UndeterminedStateException, we know the response type is an error. - status = ResponseType.ERROR; - - logger.atInfo().log(cause.getMessage()); - finished.setSuccess(); + //Since it wasn't a success, we still log what caused the ERROR + logger.atWarning().log(cause.getMessage()); + finished.setFailure(cause); + //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } - - /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ - @VisibleForTesting - ResponseType getStatus() { - return status; - } -} - +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 69d5b7f1603..1ec4e314813 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -22,13 +22,12 @@ import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -62,27 +61,17 @@ public class WebWhoisActionHandler extends ActionHandler { /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ private final HttpRequestMessage requestMessage; - /** Default port for http. */ - private int httpPort; - - /** default port for https. */ - private int httpsPort; - @Inject public WebWhoisActionHandler( @WebWhoisProtocol Bootstrap bootstrap, @HttpWhoisProtocol Protocol httpWhoisProtocol, @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage, - @HttpWhoisProtocol int httpPort, - @HttpsWhoisProtocol int httpsPort) { + HttpRequestMessage requestMessage) { this.bootstrap = bootstrap; this.httpWhoisProtocol = httpWhoisProtocol; this.httpsWhoisProtocol = httpsWhoisProtocol; this.requestMessage = requestMessage; - this.httpPort = httpPort; - this.httpsPort = httpsPort; } @@ -93,7 +82,7 @@ public WebWhoisActionHandler( */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -112,7 +101,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -123,12 +112,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; - if (newPort == httpPort) { + if (url.getProtocol().equals(httpWhoisProtocol.name())) { newProtocol = httpWhoisProtocol; - } else if (newPort == httpsPort) { + } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -143,34 +132,38 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) .setHost(newHost) .build(); - //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); - //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..b4c01d06a8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,12 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..f1b2d6ac6a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -25,11 +25,7 @@ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { - super(version, status); - } - - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index be6c872cc3e..6e3da3f69d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,7 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline @@ -22,8 +22,9 @@ public interface OutboundMessageType { /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - public OutboundMessageType modifyMessage(String... args) throws InternalException; + OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - public String name(); + @Override + String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dd1882b5686..dab5851e8d8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,16 +14,18 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.ProbingSequence; +import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} - * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} + * in a single loop of a {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * in a {@link ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -31,17 +33,21 @@ */ public abstract class Token { - /** {@link Channel} that always starts out as null. */ + /** + * {@link Channel} that always starts out as null. Once a persistent connection + * is made (such as EPP), that channel is stored in the token and passed on to + * later steps in the sequence until a new loop begins. + */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String getHost(); + public abstract String host(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 2847e5ce0eb..bb06ee89db6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import javax.inject.Inject; import javax.inject.Named; @@ -33,42 +33,38 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final String prefix; + private final static String PREFIX = "whois.nic."; /** {@link ImmutableList} of all top level domains to be probed. */ - private final ImmutableList topLevelDomains; + private final Iterator topLevelDomainsIterator; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private int domainsIndex; + private String currentDomain; @Inject - public WebWhoisToken( - @Named("Web-WHOIS-Prefix") String prefix, - @WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { - domainsIndex = 0; - this.prefix = prefix; - this.topLevelDomains = topLevelDomains; + topLevelDomainsIterator = topLevelDomains.iterator(); + currentDomain = topLevelDomainsIterator.next(); } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - domainsIndex += 1; - domainsIndex %= topLevelDomains.size(); + currentDomain = topLevelDomainsIterator.next(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { - return original.modifyMessage(getHost()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + return original.modifyMessage(host()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String getHost() { - return prefix + topLevelDomains.get(domainsIndex); + public String host() { + return PREFIX + currentDomain; } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( { - ProbingSequence sequence = new ProbingSequence.Builder() - .addStep(firstStepBuilder) - .addStep(secondStepBuilder) - .addStep(thirdStepBuilder) - .addToken(testToken) - .setBootstrap(dummyBootstrap) - .build(); - }); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index ee38e7cdf74..7bba9d66782 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.TestUtils.dummyStep; import static google.registry.monitoring.blackbox.TestUtils.testStep; import static google.registry.testing.JUnitBackports.assertThrows; @@ -90,7 +91,7 @@ public class ProbingStepTest { /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ private void setupNewChannelToken() { - testToken = new NewChannelToken(""); + testToken = new NewChannelToken(ADDRESS_NAME); } /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ @@ -101,6 +102,7 @@ private void setupExistingChannelToken() { /** Sets up an embedded channel to contain the two handlers we created already */ private void setupChannel() { channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 161304c1f04..68bdd0bcef0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,7 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,8 +26,6 @@ import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpMessage; @@ -39,7 +37,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; -import java.net.Socket; import java.net.SocketAddress; import javax.annotation.Nullable; import javax.inject.Provider; @@ -148,15 +145,10 @@ public String toString() { } @Override - public OutboundMessageType modifyMessage(String... args) throws InternalException { + public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { message = args[0]; return this; } - - @Override - public String name() { - return "Test Message of: " + this.toString(); - } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ @@ -166,7 +158,6 @@ public static ProbingStep testStep(Protocol protocol, String testMessage, Bootst .setDuration(Duration.ZERO) .setMessageTemplate(new DuplexMessageTest(testMessage)) .setBootstrap(bootstrap) - .setAddress(address) .build(); } @@ -203,12 +194,6 @@ Bootstrap bootstrap() { return null; } - @Nullable - @Override - SocketAddress address() { - return null; - } - @Override public void accept(Token token) { future.setSuccess(token); @@ -241,7 +226,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String getHost() { + public String host() { return host; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index 67963805733..295bb809a13 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -17,12 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -37,7 +35,7 @@ public class TokenTest { private static String TEST_STARTER = "starter"; private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { @@ -49,7 +47,7 @@ public void testWebToken_MessageModificationSuccess() { try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index e170fad8b8c..3ecbdcc0d06 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -29,7 +29,7 @@ public class TestActionHandler extends ActionHandler { @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 72d5d5078df..2483bd65b1f 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,21 +15,23 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; @@ -64,11 +66,9 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); private static final Protocol STANDARD_PROTOCOL = Protocol.builder() .setHandlerProviders(ImmutableList.of()) - .setName("test_protocol") + .setName("http") .setPersistentConnection(false) .setPort(HTTPS_PORT) .build(); @@ -80,8 +80,10 @@ public class WebWhoisActionHandlerTest { private ProbingAction probingAction; private Provider actionHandlerProvider; - private void generateLocalAddress() { - address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + private String generateLocalAddress(String addressString) { + String modifiedAddress = addressString + System.currentTimeMillis(); + address = new LocalAddress(modifiedAddress); + return modifiedAddress; } /** Creates default protocol with empty list of handlers and specified other inputs */ @@ -100,9 +102,7 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT bootstrap, STANDARD_PROTOCOL, STANDARD_PROTOCOL, - messageTemplate, - 80, - 443 + messageTemplate ); actionHandlerProvider = new TestProvider<>(actionHandler); } @@ -111,10 +111,8 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - setupProbingActionBasic( - protocol, - outboundMessage, - makeBootstrap(new NioEventLoopGroup(1))); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -123,26 +121,23 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } /**Sets up probingAction for when testing redirection */ - private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) .setHost(TARGET_HOST) - .setAddress(DEFAULT_ADDRESS) .setChannel(channel) .build(); } - private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) .setBootstrap(bootstrap) - .setHost(host) - .setAddress(address) + .setHost(addressString) .build(); } @@ -157,8 +152,6 @@ public void testBasic_responseOk() throws Exception { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseOk", 0, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); @@ -185,13 +178,12 @@ public void testBasic_responseOk() throws Exception { } @Test - public void testBasic_responseFailure() { + public void testBasic_responseFailure_badRequest() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseBad", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -211,19 +203,18 @@ public void testBasic_responseFailure() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testBasic_responseError() { + public void testBasic_responseFailure_badURL() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseError", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -243,9 +234,9 @@ public void testBasic_responseError() { //assesses that listener is triggered, and event is success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException); } @Test @@ -257,7 +248,6 @@ public void testBasic_redirectCloseChannel() { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("redirectHttp", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -282,44 +272,15 @@ public void testBasic_redirectCloseChannel() { } @Test - public void testBasic_redirectHost() { + public void testAdvanced_responseOk() throws UndeterminedStateException { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); - HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); - - - //store future - ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); - - - channel.writeInbound(originalResponse); - - Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - } - - @Test - public void testAdvanced_responseOk() throws InternalException { - //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); @@ -329,22 +290,21 @@ public void testAdvanced_responseOk() throws InternalException { } @Test - public void testAdvanced_responseFailure() throws InternalException { + public void testAdvanced_responseFailure() throws UndeterminedStateException { //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); + String host = generateLocalAddress(TARGET_HOST); HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(bootstrap, msg); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + assertThrows(FailureException.class, future::syncUninterruptibly); } } From 665b066e8636882c65b58a1161a992518a1ebabf Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:48:33 -0400 Subject: [PATCH 202/337] SpotlessApply run to fix style issues --- prober/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index 77b1e2de2de..c86568e7672 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From a09fbc63a619e36bfd1f5127a4fd99237f763cf0 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:28:40 -0400 Subject: [PATCH 203/337] Added license header and newline where appropriate. --- prober/build.gradle | 1 + .../monitoring/blackbox/ProbingAction.java | 1 - .../blackbox/handlers/ActionHandler.java | 2 +- .../monitoring/blackbox/ProbingSequenceTest.java | 14 ++++++++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index 26d44c0a465..70b8e2a6b8b 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -35,6 +35,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] + compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 67494dd5f78..a8740e21c20 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -240,7 +240,6 @@ public ProbingAction build() { InetAddress hostAddress = InetAddress.getByName(host()); address = new InetSocketAddress(hostAddress, protocol().port()); } catch (UnknownHostException e) { - System.out.println("test"); address = new LocalAddress(host()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 0c9e93cc6dd..8a108b81006 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -97,4 +97,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } -} \ No newline at end of file +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2a8d5ebe233..8d9e45c6a66 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; From e2931f33b5034583c024598b85ae04022f5e542d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 204/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/ProbingStepTest.java | 1 - .../blackbox/TestServers/WebWhoisServer.java | 3 +- .../monitoring/blackbox/TestUtils.java | 35 +------------------ .../blackbox/handlers/ConversionHandler.java | 5 ++- .../blackbox/handlers/NettyRule.java | 4 ++- 5 files changed, 10 insertions(+), 38 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 7bba9d66782..73b104ae5dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -174,7 +174,6 @@ public void testNewChannel() throws Exception { //checks that when the future is successful, we pass down the requisite token assertThat(future.get()).isEqualTo(testToken); - } @Test diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 337d755e971..e7f125bb906 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; @@ -80,7 +81,7 @@ static class RedirectHandler extends ChannelDuplexHandler { /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 68bdd0bcef0..cc8e1512fe9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; @@ -28,17 +27,13 @@ import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpMethod;; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; import java.net.SocketAddress; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -272,33 +267,5 @@ public void addToHost(String suffix) { } } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index a8506a996a9..196141bb875 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b38c1911940..1d14cf131e6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -26,6 +26,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.ProbingActionTest; +import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; @@ -54,7 +56,7 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { From a8a53a2100a275f861e24b43d131fb47ef403ec8 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 5 Aug 2019 16:16:36 -0400 Subject: [PATCH 205/337] Refactored ProbingAction to minimize number of unnecessary methods --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 4 +- .../monitoring/blackbox/ProbingAction.java | 160 ++++++++---------- .../monitoring/blackbox/ProbingStep.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 4 +- .../blackbox/handlers/ActionHandler.java | 2 +- .../handlers/WebWhoisActionHandler.java | 7 +- .../blackbox/messages/HttpRequestMessage.java | 5 +- .../blackbox/ProbingActionTest.java | 130 +++++++------- .../blackbox/ProbingSequenceTest.java | 25 ++- .../monitoring/blackbox/ProbingStepTest.java | 6 + .../monitoring/blackbox/TestUtils.java | 2 +- .../handlers/WebWhoisActionHandlerTest.java | 9 +- 13 files changed, 176 insertions(+), 183 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 307afd34d81..e12d1f0f522 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; import java.util.Set; @@ -29,7 +30,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); + Set sequences = proberComponent.sequences(); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 1db97d1b581..fb83b236b69 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -49,7 +49,7 @@ EventLoopGroup provideEventLoopGroup() { /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides @Singleton - Class provideChannelClass() { + Class provideChannelClazz() { return NioSocketChannel.class; } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @@ -77,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - Set provideAllSequences(); + Set sequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index a8740e21c20..25c3a1c17d6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -33,10 +33,8 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -69,6 +67,8 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -85,6 +85,7 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ @@ -94,108 +95,89 @@ public abstract class ProbingAction implements Callable { public abstract String host(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } - /** - * The method that performs the work of the actual action. + * Performs the work of the actual action * - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ *

First, checks if channel is active by setting a listener to perform the bulk of the work + * when the connection future is successful.

+ * + *

Once the connection is successful, we establish which of the handlers in the pipeline is + * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when + * we receive an expected response from the server.

+ * + *

Next, we set a timer set to a specified delay. After the delay has passed, we send the + * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, + * we inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - - //ChannelPromise that we use to inform ProbingStep when we are finished. - ChannelPromise finished = channel().newPromise(); - - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - - return finished; - } /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws UndeterminedStateException { + public ChannelFuture call() { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); + + //Ensures channel has been set up with connection future as an attribute + checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + //When connection is established call super.call and set returned listener to success channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { + (ChannelFuture connectionFuture) -> { + if (connectionFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); + ActionHandler actionHandler; + try { + actionHandler = channel().pipeline().get(ActionHandler.class); + } catch (ClassCastException e) { + //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); + } + + ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> { + if (future.isSuccess()) { + finished.setSuccess(); + } else { + finished.setFailure(future.cause()); + } + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) { + logger.atInfo() + .log("Closed stale channel. Moving on to next ProbingStep"); + } else { + logger.atWarning() + .log( + "Could not close channel. Stale connection still exists."); + } + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); } else { //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( + logger.atSevere().withCause(connectionFuture.cause()).log( "Cannot connect to relay channel for %s channel: %s.", protocol().name(), this.channel()); ChannelFuture unusedFuture = channel().close(); @@ -228,7 +210,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract Protocol protocol(); - abstract Optional channel(); + abstract Channel channel(); abstract String host(); @@ -243,11 +225,11 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { + if (channel() == null) { bootstrap.handler( new ChannelInitializer() { @Override diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index ca980100067..3df536a9478 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -135,7 +135,7 @@ public void accept(Token token) { try { //call the generated action future = currentAction.call(); - } catch(UndeterminedStateException e) { + } catch(Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index c5e41fea38b..2e640338511 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -184,10 +184,10 @@ static SslClientInitializer provideSslClientInitializer(SslPro @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClass){ + Class channelClazz){ return new Bootstrap() .group(eventLoopGroup) - .channel(channelClass); + .channel(channelClazz); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 8a108b81006..55c9123e3a5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -46,7 +46,7 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler testHandlerProvider = new TestProvider<>(testHandler); private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - private ProbingAction newChannelAction; - private ProbingAction existingChannelAction; - private EmbeddedChannel channel; - private Protocol protocol; - /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** Sets up a {@link Protocol} corresponding to when a new connection is created */ - private void setupNewChannelProtocol() { - protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - } - /** Sets up a {@link Protocol} corresponding to when a new connection exists */ - private void setupExistingChannelProtocol() { - protocol = Protocol.builder() + + + + @Test + public void testBehavior_existingChannel() throws UndeterminedStateException { + //setup + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up a Protocol corresponding to when a connection exists. + Protocol protocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) .build(); - } - - /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ - private void setupNewChannelAction() { - newChannelAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - } - - private void setupChannel() { - channel = new EmbeddedChannel(); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ - private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ProbingAction.builder() + // Sets up a ProbingAction that creates a channel using test specified attributes. + ProbingAction action = ProbingAction.builder() .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) .setHost("") .build(); - } - - @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { - //setup - setupChannel(); - setupExistingChannelProtocol(); - channel.pipeline().addLast(conversionHandler); - channel.pipeline().addLast(testHandler); - setupExistingChannelAction(channel); + //tests main function of ProbingAction + ChannelFuture future = action.call(); - ChannelFuture future = existingChannelAction.call(); - - //Ensures that we pass in the right message to the channel and haven't marked the future as success yet - Object msg = channel.readOutbound(); + //Obtains the outboundMessage passed through pipeline after delay + Object msg = null; + while (msg == null) { + msg = channel.readOutbound(); + } + //tests the passed message is exactly what we expect assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - assertThat(response).isEqualTo(TEST_MESSAGE); - assertThat(future.isSuccess()).isFalse(); + String request = ((ByteBuf) msg).toString(UTF_8); + assertThat(request).isEqualTo(TEST_MESSAGE); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -158,18 +122,40 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { @Test public void testSuccess_newChannel() throws Exception { //setup - setupNewChannelProtocol(); + + LocalAddress address = new LocalAddress(ADDRESS_NAME); + Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + // Sets up a Protocol corresponding to when a new connection is created. + Protocol protocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) + .build(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - setupNewChannelAction(); - ChannelFuture future = newChannelAction.call(); + + // Sets up a ProbingAction with existing channel using test specified attributes. + ProbingAction action = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) + .build(); + + //tests main function of ProbingAction + ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.sync(); + future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()); + assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 8d9e45c6a66..e5f91a300d6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -18,27 +18,44 @@ import static google.registry.testing.JUnitBackports.assertThrows; import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.TestUtils.TestToken; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import java.net.SocketAddress; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; @RunWith(JUnit4.class) public class ProbingSequenceTest { private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new ProbingSequenceTestToken(); + private Token testToken = new TestToken("") { + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + }; + private void setupMock(ProbingStep mock, ProbingStep nextStep) { + Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + } /** * Custom {@link ProbingStep} subclass that acts as a mock * step, so we can test how well {@link ProbingSequence} builds * a linked list of {@link ProbingStep}s from their {@link Builder}s. */ + private static class TestStep extends ProbingStep { private String marker; @@ -92,9 +109,9 @@ public void specialAccept(Token token) { @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 73b104ae5dc..256eeb0b29d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -45,6 +45,7 @@ import javax.inject.Provider; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ public class ProbingStepTest { @@ -191,6 +192,11 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); + Object msg = channel.readOutbound(); + + while (msg == null) { + msg = channel.readOutbound(); + } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index cc8e1512fe9..ef9926a7620 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -204,7 +204,7 @@ public String toString() { } /** Basic outline for {@link Token} instances to be used in tests */ - private static abstract class TestToken extends Token { + static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 2483bd65b1f..5fa39b1da83 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -41,7 +41,6 @@ import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; import org.joda.time.Duration; @@ -156,7 +155,7 @@ public void testBasic_responseOk() throws Exception { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); @@ -187,7 +186,7 @@ public void testBasic_responseFailure_badRequest() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -218,7 +217,7 @@ public void testBasic_responseFailure_badURL() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -251,7 +250,7 @@ public void testBasic_redirectCloseChannel() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early From dc93bf9f47c81a7920f7d38e72e49ed4bfd6e6f0 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 15:45:32 -0400 Subject: [PATCH 206/337] Modified tests for WebWhois according to changes suggested by laijiang. --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 2 - .../monitoring/blackbox/ProbingAction.java | 1 - .../monitoring/blackbox/WebWhoisModule.java | 10 +- .../blackbox/ProbingActionTest.java | 20 +- .../blackbox/ProbingSequenceTest.java | 120 ++++------- .../monitoring/blackbox/ProbingStepTest.java | 187 ++++++++--------- .../blackbox/TestServers/TestServer.java | 38 ---- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 142 +------------ .../monitoring/blackbox/TokenTest.java | 59 ------ .../blackbox/handlers/ConversionHandler.java | 6 +- .../blackbox/handlers/NettyRule.java | 46 +++- .../handlers/SslClientInitializerTest.java | 5 - .../blackbox/handlers/TestActionHandler.java | 7 +- .../handlers/WebWhoisActionHandlerTest.java | 197 +++++++----------- .../blackbox/messages/TestMessage.java | 4 + 17 files changed, 264 insertions(+), 589 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index e12d1f0f522..5ca423c29cc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -30,7 +29,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.sequences(); + ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index fb83b236b69..f9db4865f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,11 +14,9 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 25c3a1c17d6..0265390fafe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -138,7 +138,6 @@ public ChannelFuture call() { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); timer.newTimeout(timeout -> { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 2e640338511..de041afad38 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,14 +17,11 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -33,10 +30,7 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index b5d8f7599c4..ec5ee5d77ec 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,17 +20,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -39,9 +37,9 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; import javax.inject.Provider; import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,10 +72,9 @@ public class ProbingActionTest { public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - + @Ignore @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { + public void testBehavior_existingChannel() { //setup EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -95,7 +92,7 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost("") .build(); @@ -112,6 +109,9 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { String request = ((ByteBuf) msg).toString(UTF_8); assertThat(request).isEqualTo(TEST_MESSAGE); + // Ensures that we haven't marked future as done until response is received. + assertThat(future.isDone()).isFalse(); + //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); assertThat(future.isSuccess()).isTrue(); @@ -143,7 +143,7 @@ public void testSuccess_newChannel() throws Exception { .setBootstrap(bootstrap) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost(ADDRESS_NAME) .build(); @@ -151,7 +151,7 @@ public void testSuccess_newChannel() throws Exception { ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index e5f91a300d6..5c4452df7b3 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -15,17 +15,11 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; -import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; -import google.registry.monitoring.blackbox.TestUtils.TestToken; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import java.net.SocketAddress; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,85 +27,31 @@ @RunWith(JUnit4.class) public class ProbingSequenceTest { - private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new TestToken("") { - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - }; - - private void setupMock(ProbingStep mock, ProbingStep nextStep) { - Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + private ProbingStep setupMock() { + ProbingStep mock = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(mock).nextStep(); + return mock; } - /** - * Custom {@link ProbingStep} subclass that acts as a mock - * step, so we can test how well {@link ProbingSequence} builds - * a linked list of {@link ProbingStep}s from their {@link Builder}s. - */ - - private static class TestStep extends ProbingStep { - private String marker; - - /** We implement all abstract methods to simply return null, as we have no use for them here. */ - @Override - Duration duration() { - return null; - } - @Override - Protocol protocol() { - return null; - } + private static class Wrapper { - @Override - OutboundMessageType messageTemplate() { - return null; - } + T data; - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ - @Override - Bootstrap bootstrap() { - return null; - } - - public TestStep(String marker) { - this.marker = marker; - } - - /** - * On a call to accept, we modify the token to reflect what the current step is, so we can get - * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated - * in order. - */ - @Override - public void accept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - if (!isLastStep) { - nextStep().accept(token); - } else { - ((TestStep)nextStep()).specialAccept(token); - } - } - - /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ - public void specialAccept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - return; + public Wrapper(T data) { + this.data = data; } } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = Mockito.mock(ProbingStep.class); - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) @@ -119,16 +59,25 @@ public void testSequenceBasicConstruction_Success() { .addStep(thirdStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(thirdStep); + assertThat(thirdStep.nextStep()).isEqualTo(firstStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); + assertThat(wrapper.data).isTrue(); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(thirdStep) @@ -137,9 +86,16 @@ public void testSequenceAdvancedConstruction_Success() { .addStep(firstStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(firstStep); + assertThat(thirdStep.nextStep()).isEqualTo(secondStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); + assertThat(wrapper.data).isTrue(); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 256eeb0b29d..91a113940e8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,18 +11,19 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.TestUtils.dummyStep; -import static google.registry.monitoring.blackbox.TestUtils.testStep; -import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; import google.registry.monitoring.blackbox.TestUtils.TestProvider; @@ -30,19 +31,20 @@ import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; +import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; @@ -51,18 +53,18 @@ public class ProbingStepTest { /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final static String ADDRESS_NAME = "TEST_ADDRESS"; + private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final static int PROTOCOL_PORT = 0; + private final static String TEST_MESSAGE = "TEST_MESSAGE"; + private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -73,117 +75,108 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(ADDRESS_NAME); + /** + * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} + * is called, it just marks the supplied future as succeeded, returning the requisite token. + */ + private ProbingStep dummyStep() { + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(dummyStep).nextStep(); + return dummyStep; } - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); - dummyStep = dummyStep(eventLoopGroup); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - } + @Test + public void testNewChannel() throws Exception { + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() + // Sets up Protocol for when we create a new channel. + Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); - } - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) .build(); - } - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - //there should be no next step - assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); - } + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); - @Test - public void testNewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + //Set up blackbox server that receives our messages then echoes them back to us + nettyRule.setUpServer(address); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); + verify(dummyStep, times(1)).accept(any(Token.class)); } + @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupChannel(); - setupExistingChannelToken(); + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); + + // Sets up Protocol for when a channel already exists. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) + .build(); + + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) + .build(); + + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + + // Sets up an embedded channel to contain the two handlers we created already. + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + + //Assures that the channel has a succeeded connectionFuture. + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. + Token testToken = new ExistingChannelToken(channel, ""); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -200,17 +193,13 @@ public void testWithSequence_ExistingChannel() throws Exception { //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); + //At this point, we should have received the message, so the future obtained should be marked + // as a success + verify(dummyStep, times(1)).accept(any(Token.class)); - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index a4474b6b8b5..12e25a6bc6c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -14,24 +14,16 @@ package google.registry.monitoring.blackbox.TestServers; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; - import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform @@ -65,35 +57,5 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index e7f125bb906..4da75b31c25 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -74,7 +75,7 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends ChannelDuplexHandler { + static class RedirectHandler extends SimpleChannelInboundHandler { private String redirectInput; private String destinationInput; @@ -90,8 +91,7 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - HttpRequest request = (HttpRequest) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index ef9926a7620..2567a7cc155 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,42 +16,24 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMethod;; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.concurrent.DefaultPromise; -import java.net.SocketAddress; import javax.inject.Provider; -import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { - static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -76,33 +58,13 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); + response.headers().set("content-type", "text/plain"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); return response; } @@ -121,88 +83,6 @@ public E get() { } } - /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ - public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { - - String message; - - public DuplexMessageTest() { - message = ""; - } - - public DuplexMessageTest(String msg) { - message = msg; - } - - @Override - public String toString() { - return message; - } - - @Override - public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { - message = args[0]; - return this; - } - } - - /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .build(); - - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); - } - - /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { - private DefaultPromise future; - - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; - } - - @Override - public void accept(Token token) { - future.setSuccess(token); - } - public DefaultPromise getFuture() { - return future; - } - - @Override - public String toString() { - return "Dummy Step"; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; @@ -251,21 +131,5 @@ public Channel channel() { return channel; } } - - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java deleted file mode 100644 index 295bb809a13..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) - */ -@RunWith(JUnit4.class) -public class TokenTest { - - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - - public Token webToken = new WebWhoisToken(TEST_DOMAINS); - - @Test - public void testWebToken_MessageModificationSuccess() { - //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); - - //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { - throw new RuntimeException(e); - } - - - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 196141bb875..c9d337d6ad8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -32,7 +32,7 @@ * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +40,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 1d14cf131e6..86b54d9a07d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -25,14 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -44,7 +41,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -55,7 +51,7 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + *

Code based on and almost identical to {@code NettyRule} in the proxy. * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -83,10 +79,12 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + ImmutableList.builder().add(handlers).add(echoHandler).build()); } /** Sets up a client channel connecting to the give local address. */ @@ -124,7 +122,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertThatCustomWorks(String message) throws Exception { + public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -165,6 +163,38 @@ ThrowableSubject assertThatClientRootCause() { } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** + * Saves any inbound error as the cause of the promise failure. + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 83c8e132f07..523fb228752 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -22,12 +22,7 @@ import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 3ecbdcc0d06..95b06e623d1 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -25,17 +25,16 @@ */ public class TestActionHandler extends ActionHandler { - private String receivedMessage; + private InboundMessageType receivedMessage; @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage.toString(); + receivedMessage = inboundMessage; super.channelRead0(ctx, inboundMessage); } - @Override - public String toString() { + public InboundMessageType getResponse() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 5fa39b1da83..3667f3f3d9a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -20,7 +20,6 @@ import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; -import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; @@ -28,13 +27,11 @@ import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; @@ -56,6 +53,7 @@ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -65,11 +63,12 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of()) + private final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( + null, null, null, null)))) .setName("http") .setPersistentConnection(false) - .setPort(HTTPS_PORT) + .setPort(HTTP_PORT) .build(); @@ -78,14 +77,13 @@ public class WebWhoisActionHandlerTest { private ActionHandler actionHandler; private ProbingAction probingAction; private Provider actionHandlerProvider; + private Protocol initialProtocol; + private HttpRequestMessage msg; - private String generateLocalAddress(String addressString) { - String modifiedAddress = addressString + System.currentTimeMillis(); - address = new LocalAddress(modifiedAddress); - return modifiedAddress; - } - /** Creates default protocol with empty list of handlers and specified other inputs */ + /** + * Creates default protocol with empty list of handlers and specified other inputs + */ private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() .setName(name) @@ -95,7 +93,9 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect .build(); } - /** Initializes new WebWhoisActionHandler */ + /** + * Initializes new WebWhoisActionHandler + */ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, @@ -106,12 +106,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT actionHandlerProvider = new TestProvider<>(actionHandler); } - /** Sets up testing channel with requisite attributes */ + /** + * Sets up testing channel with requisite attributes + */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -119,18 +120,9 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .group(group) .channel(LocalChannel.class); } - /**Sets up probingAction for when testing redirection */ - private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setHost(TARGET_HOST) - .setChannel(channel) - .build(); - } - private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { + private void setupProbingActionWithoutChannel(Protocol protocol, + HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) @@ -140,171 +132,124 @@ private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMess .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + private void setupLocalServer(String redirectInput, String destinationInput, + EventLoopGroup group) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testBasic_responseOk() throws Exception { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { + msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, true); + initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + } + + @Test + public void testBasic_responseOk() { + //setup + setup("", null, true); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure_badRequest() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseBad", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage( + makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same assertThat(future.cause() instanceof FailureException).isTrue(); } - @Test - public void testBasic_responseFailure_badURL() { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseError", 0, true); - setupChannel(initialProtocol, msg); - - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, and event is success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); - } @Test - public void testBasic_redirectCloseChannel() { + public void testBasic_responseFailure_badURL() { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - //checks that future has not been set to successful or a failure - assertThat(testPromise.isSuccess()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - + //assesses that listener is triggered, and event is success + assertThat(future.isDone()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + //ensures Protocol is the same + assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_responseOk() throws UndeterminedStateException { - //setup + public void testAdvanced_redirect() { + // Sets up EventLoopGroup with 1 thread to be blocking. EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + // Sets up embedded channel. + setup("", makeBootstrap(group), false); + setupChannel(initialProtocol, msg); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); - } + // Initializes LocalAddress with unique String. + String host = TARGET_HOST + System.currentTimeMillis(); + address = new LocalAddress(host); - @Test - public void testAdvanced_responseFailure() throws UndeterminedStateException { - //setup - EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); + //stores future + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); + + // Sets up the local server that the handler will be redirected to. setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + FullHttpResponse response = + new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, + HTTP_REDIRECT + host, true, false)); + + //checks that future has not been set to successful or a failure + assertThat(future.isDone()).isFalse(); + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); //assesses that we successfully received good response and protocol is unchanged - assertThrows(FailureException.class, future::syncUninterruptibly); + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index 922c3052bda..c31a9d336bd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,6 +24,10 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; + public TestMessage() { + this(""); + } + public TestMessage(String msg) { message = msg; } From 705d2628da7200e933fbdebacd4c6887225f8da2 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 16:42:43 -0400 Subject: [PATCH 207/337] Removed TestProvider from TestUtils. --- .../blackbox/ProbingActionTest.java | 7 ++-- .../monitoring/blackbox/ProbingStepTest.java | 11 +++--- .../blackbox/TestServers/TestServer.java | 3 -- .../monitoring/blackbox/TestUtils.java | 17 --------- .../handlers/WebWhoisActionHandlerTest.java | 36 ++++++------------- .../blackbox/messages/TestMessage.java | 4 --- 6 files changed, 18 insertions(+), 60 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index ec5ee5d77ec..f7857dd80f9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -64,8 +63,8 @@ public class ProbingActionTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + private Provider testHandlerProvider = () -> testHandler; + private Provider conversionHandlerProvider = () -> conversionHandler; /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -156,7 +155,7 @@ public void testSuccess_newChannel() throws Exception { future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 91a113940e8..1f09dd13553 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -90,9 +89,8 @@ private ProbingStep dummyStep() { @Test public void testNewChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when we create a new channel. Protocol testProtocol = Protocol.builder() @@ -142,9 +140,8 @@ public void testNewChannel() throws Exception { @Test public void testWithSequence_ExistingChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when a channel already exists. Protocol testProtocol = Protocol.builder() diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 12e25a6bc6c..46615a506fb 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -29,15 +29,12 @@ * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { - private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - this.localAddress = localAddress; - //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 2567a7cc155..50c60d9fc52 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -21,7 +21,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -29,7 +28,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Provider; /** Utility class for various helper methods used in testing. */ public class TestUtils { @@ -68,21 +66,6 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ - public static class TestProvider implements Provider { - - private E obj; - - public TestProvider(E obj) { - this.obj = obj; - } - - @Override - public E get() { - return obj; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 3667f3f3d9a..33eb190a66a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -25,7 +25,6 @@ import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; @@ -64,18 +63,16 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( - null, null, null, null)))) + .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( + null, null, null, null))) .setName("http") .setPersistentConnection(false) .setPort(HTTP_PORT) .build(); - private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; - private ProbingAction probingAction; private Provider actionHandlerProvider; private Protocol initialProtocol; private HttpRequestMessage msg; @@ -103,13 +100,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT STANDARD_PROTOCOL, messageTemplate ); - actionHandlerProvider = new TestProvider<>(actionHandler); + actionHandlerProvider = () -> actionHandler; } /** * Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + private void setupChannel(Protocol protocol) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -121,19 +118,8 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } - private void setupProbingActionWithoutChannel(Protocol protocol, - HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(addressString) - .build(); - } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group) { + EventLoopGroup group, LocalAddress address) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } @@ -148,7 +134,7 @@ private void setup(String hostName, Bootstrap bootstrap, boolean persistentConne public void testBasic_responseOk() { //setup setup("", null, true); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -169,7 +155,7 @@ public void testBasic_responseOk() { public void testBasic_responseFailure_badRequest() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -195,7 +181,7 @@ public void testBasic_responseFailure_badRequest() { public void testBasic_responseFailure_badURL() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -224,18 +210,18 @@ public void testAdvanced_redirect() { // Sets up embedded channel. setup("", makeBootstrap(group), false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); // Initializes LocalAddress with unique String. String host = TARGET_HOST + System.currentTimeMillis(); - address = new LocalAddress(host); + LocalAddress address = new LocalAddress(host); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group); + setupLocalServer("", host, group, address); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index c31a9d336bd..922c3052bda 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,10 +24,6 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; - public TestMessage() { - this(""); - } - public TestMessage(String msg) { message = msg; } From f79d80b510b58635f585b4a4d27282ff04aa5a6a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 09:46:27 -0400 Subject: [PATCH 208/337] Rebased to master --- .../monitoring/blackbox/handlers/ActionHandler.java | 7 +++++-- .../monitoring/blackbox/TestServers/WebWhoisServer.java | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 55c9123e3a5..eda82c59a37 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -33,8 +33,11 @@ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} - * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * of the error. If the error is an instance of a {@link FailureException} {@code finished} is + * marked as a failure with cause {@link FailureException}. If it is any other type of error, it + * is treated as an {@link UndeterminedStateException} and {@code finished} set as a failure with + * the same cause as what caused the exception. Lastly, if no error is thrown, we know the action + * completed as a success, and, as such, we mark {@code finished} as a success.

* *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 4da75b31c25..28b36190a7e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; From c21953eff9d6a9c663f1061eb1bec8bbfa35a8c0 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 11:26:33 -0400 Subject: [PATCH 209/337] Updated issues in rebasing --- core/src/main/java/google/registry/ui/package-info.java | 1 - core/src/main/java/google/registry/xjc/package-info.java | 1 - 2 files changed, 2 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..ddff37c6807 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -14,4 +14,3 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.ui; - diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..5b5456585cc 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -14,4 +14,3 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.xjc; - From e46445aa2eb750315f066e394d7a340f5be24388 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 12:33:30 -0400 Subject: [PATCH 210/337] Minor style change on prober/build.gradle --- core/src/main/java/google/registry/cron/package-info.java | 2 +- core/src/main/java/google/registry/xml/package-info.java | 2 +- prober/build.gradle | 1 - .../registry/monitoring/blackbox/handlers/ActionHandler.java | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/google/registry/cron/package-info.java b/core/src/main/java/google/registry/cron/package-info.java index 49b18ca2885..459f2513f93 100644 --- a/core/src/main/java/google/registry/cron/package-info.java +++ b/core/src/main/java/google/registry/cron/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xml/package-info.java b/core/src/main/java/google/registry/xml/package-info.java index b3f27868b91..f8e42585ecc 100644 --- a/core/src/main/java/google/registry/xml/package-info.java +++ b/core/src/main/java/google/registry/xml/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/prober/build.gradle b/prober/build.gradle index 70b8e2a6b8b..3652390d0ba 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -53,4 +53,3 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index eda82c59a37..8f2319b3d39 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -60,7 +60,7 @@ public void handlerAdded(ChannelHandlerContext ctx) { finished = ctx.newPromise(); } - /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ + /** Marks {@link ChannelPromise} as success */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { From 40624f0bf5f0c1337d5381570fc4521d6224399e Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 15:11:53 -0400 Subject: [PATCH 211/337] Fixed warnings for java compilation --- .../registry/monitoring/blackbox/ProbingAction.java | 11 +++++------ .../registry/monitoring/blackbox/ProbingStep.java | 4 ++-- .../google/registry/monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/handlers/ActionHandler.java | 6 +++--- .../blackbox/handlers/WebWhoisActionHandler.java | 2 +- .../blackbox/messages/HttpRequestMessage.java | 3 ++- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 0265390fafe..c7645f29e6a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -67,8 +67,6 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -142,13 +140,14 @@ public ChannelFuture call() { timer.newTimeout(timeout -> { // Write appropriate outboundMessage to pipeline - channel().writeAndFlush(outboundMessage()); + ChannelFuture unusedFutureWriteAndFlush = + channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( future -> { if (future.isSuccess()) { - finished.setSuccess(); + ChannelFuture unusedFuture = finished.setSuccess(); } else { - finished.setFailure(future.cause()); + ChannelFuture unusedFuture = finished.setFailure(future.cause()); } }, //If we don't have a persistent connection, close the connection to this channel @@ -276,7 +275,7 @@ private static void addHandlers( @Override - public String toString() { + public final String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 3df536a9478..332a8d0de04 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -105,7 +105,7 @@ private ProbingAction generateAction(Token token) throws UndeterminedStateExcept /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { - return (isLastStep) ? token.next() : token; + return isLastStep ? token.next() : token; } /** @@ -167,7 +167,7 @@ public void accept(Token token) { } @Override - public String toString() { + public final String toString() { return String.format("ProbingStep with Protocol: %s\n" + "OutboundMessage: %s\n", protocol(), diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 92470ef62c8..b430d79507a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -58,7 +58,7 @@ public abstract static class Builder { } @Override - public String toString() { + public final String toString() { return String.format( "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", name(), diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 8f2319b3d39..6b6dad914a4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -65,7 +65,7 @@ public void handlerAdded(ChannelHandlerContext ctx) { public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - finished.setSuccess(); + ChannelFuture unusedFuture = finished.setSuccess(); } /** @@ -86,14 +86,14 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atInfo().log(cause.getMessage()); //As always, inform the ProbingStep that we successfully completed this action - finished.setFailure(cause); + ChannelFuture unusedFuture = finished.setFailure(cause); } else { //On UndeterminedStateException, we know the response type is an error. //Since it wasn't a success, we still log what caused the ERROR logger.atWarning().log(cause.getMessage()); - finished.setFailure(cause); + ChannelFuture unusedFuture = finished.setFailure(cause); //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 34eac2a0118..de20c6b9269 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -86,7 +86,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { + if (response.status().equals(HttpResponseStatus.OK)) { logger.atInfo().log("Received Successful HttpResponseStatus"); logger.atInfo().log("Response Received: " + response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 5e9300d0f34..8d285811e0d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,6 +19,7 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import java.util.Arrays; import javax.inject.Inject; /** @@ -69,7 +70,7 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx throw new IllegalArgumentException( String.format( "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + args, args.length)); + + " Received %d arguments instead of: " + Arrays.toString(args), args.length)); } } From b4bfc3577998a4c4a0ca39c2287cc969b7e5ee8c Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 17:01:14 -0400 Subject: [PATCH 212/337] Fixed files to pass all style tests --- .../registry/monitoring/blackbox/Prober.java | 10 +- .../monitoring/blackbox/ProberModule.java | 32 ++++-- .../monitoring/blackbox/ProbingAction.java | 108 +++++++++++------- .../monitoring/blackbox/ProbingSequence.java | 39 ++++--- .../monitoring/blackbox/ProbingStep.java | 75 +++++++----- .../monitoring/blackbox/Protocol.java | 16 ++- .../monitoring/blackbox/WebWhoisModule.java | 80 +++++++++---- .../exceptions/ConnectionException.java | 4 +- .../UndeterminedStateException.java | 5 +- .../blackbox/handlers/ActionHandler.java | 48 +++++--- .../handlers/SslClientInitializer.java | 11 +- .../handlers/WebWhoisActionHandler.java | 53 ++++++--- .../handlers/WebWhoisMessageHandler.java | 21 ++-- .../blackbox/messages/HttpRequestMessage.java | 19 ++- .../messages/HttpResponseMessage.java | 6 +- .../blackbox/messages/InboundMessageType.java | 4 +- .../messages/OutboundMessageType.java | 10 +- .../monitoring/blackbox/tokens/Token.java | 41 ++++--- .../blackbox/tokens/WebWhoisToken.java | 36 ++++-- .../blackbox/ProbingActionTest.java | 17 ++- .../monitoring/blackbox/ProbingStepTest.java | 37 +++--- .../blackbox/TestServers/TestServer.java | 58 ---------- .../blackbox/TestServers/WebWhoisServer.java | 106 ----------------- .../monitoring/blackbox/TestUtils.java | 32 ++++-- .../blackbox/handlers/ConversionHandler.java | 16 ++- .../blackbox/handlers/NettyRule.java | 37 +++--- .../handlers/SslClientInitializerTest.java | 36 +++--- .../blackbox/handlers/TestActionHandler.java | 4 +- .../handlers/WebWhoisActionHandlerTest.java | 18 +-- .../blackbox/tokens/WebWhoisTokenTest.java | 2 - 30 files changed, 526 insertions(+), 455 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 5ca423c29cc..433d7361d5b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -18,12 +18,16 @@ import google.registry.monitoring.blackbox.ProberModule.ProberComponent; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by + * Dagger. */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + /** + * Main Dagger Component + */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() + .build(); public static void main(String[] args) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index f9db4865f78..df8b5fdbabd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -28,36 +28,50 @@ import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores - * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. + * Dagger main module, which {@link Provides} all objects that are shared between sequences and + * stores {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link + * ProbingSequence}. */ @Module public class ProberModule { - /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + /** + * Default {@link Duration} chosen to be time between each {@link ProbingAction} call. + */ private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ + /** + * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. + */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + /** + * {@link Provides} one global {@link Channel} class that is used to construct a {@link + * io.netty.bootstrap.Bootstrap}. + */ @Provides @Singleton Class provideChannelClazz() { return NioSocketChannel.class; } - /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ + + /** + * {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. + */ @Provides @Singleton Duration provideDuration() { return DEFAULT_DURATION; } - /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ + /** + * {@link Provides} the {@link SslProvider} used by instances of {@link + * google.registry.monitoring.blackbox.handlers.SslClientInitializer} + */ @Provides @Singleton static SslProvider provideSslProvider() { @@ -65,7 +79,9 @@ static SslProvider provideSslProvider() { return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - /** Root level {@link Component} that provides each {@link ProbingSequence}. */ + /** + * Root level {@link Component} that provides each {@link ProbingSequence}. + */ @Singleton @Component( modules = { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index c7645f29e6a..cdb099e4a76 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -26,40 +26,42 @@ import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; +import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; import javax.inject.Provider; +import org.joda.time.Duration; /** * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the - * task has been completed

+ * to perform its specified task, and return the {@link ChannelFuture} that will be informed when + * the task has been completed

* - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. - * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} - * gives the outline and {@link ProbingAction} gives the details of that connection.

+ *

Is an immutable class, as it is comprised of the tools necessary for making a specific type + * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall + * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the + * details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes + * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when + * informed that the connection is successful. If the channel is supplied, the connection future is + * automatically set to successful.

*/ @AutoValue @@ -67,32 +69,51 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** + * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when + * channel is active. + */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey + .valueOf("CONNECTION_FUTURE_KEY"); - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + /** + * {@link AttributeKey} in channel that gives the information of the channel's host. + */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey + .valueOf("REMOTE_ADDRESS_KEY"); - /** {@link Timer} that rate limits probing */ + /** + * {@link Timer} that rate limits probing + */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ + /** + * Actual {@link Duration} of this delay + */ public abstract Duration delay(); - /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ + /** + * {@link OutboundMessageType} instance that we write and flush down pipeline to server + */ public abstract OutboundMessageType outboundMessage(); - /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + /** + * {@link Channel} object that either created by or passed into this {@link ProbingAction} + * instance + */ @Nullable public abstract Channel channel(); - /** The {@link Protocol} instance that specifies type of connection */ + /** + * The {@link Protocol} instance that specifies type of connection + */ public abstract Protocol protocol(); - /** The hostname of the remote host we have a connection or will make a connection to */ + /** + * The hostname of the remote host we have a connection or will make a connection to + */ public abstract String host(); - /** * Performs the work of the actual action * @@ -111,7 +132,10 @@ public abstract class ProbingAction implements Callable { */ - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + /** + * Method that calls on {@code performAction} when it is certain channel connection is + * established. + */ @Override public ChannelFuture call() { //ChannelPromise that we return @@ -132,7 +156,8 @@ public ChannelFuture call() { try { actionHandler = channel().pipeline().get(ActionHandler.class); } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + //If we don't actually have an ActionHandler instance, we have an issue, and throw + // an UndeterminedStateException logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } @@ -150,7 +175,8 @@ public ChannelFuture call() { ChannelFuture unusedFuture = finished.setFailure(future.cause()); } }, - //If we don't have a persistent connection, close the connection to this channel + //If we don't have a persistent connection, close the connection to this + // channel future -> { if (!protocol().persistentConnection()) { @@ -163,7 +189,8 @@ public ChannelFuture call() { } else { logger.atWarning() .log( - "Could not close channel. Stale connection still exists."); + "Could not close channel. Stale connection still exists" + + "."); } } ); @@ -186,9 +213,12 @@ public ChannelFuture call() { } - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + /** + * {@link AutoValue.Builder} that does work of creating connection when not already present. + */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; public Builder setBootstrap(Bootstrap bootstrap) { @@ -223,7 +253,8 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); + checkArgument(channel() == null ^ bootstrap == null, + "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel @@ -273,14 +304,13 @@ private static void addHandlers( } - @Override public final String toString() { return String.format( - "ProbingAction with delay: %d\n" + - "outboundMessage: %s\n" + - "protocol: %s\n" + - "host: %s\n", + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 91c4165c068..175cf4dcfa5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -23,16 +23,21 @@ * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * * - *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

+ *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} + * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one + * is the first repeated step.

* - *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

+ *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once + * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest + * of the work.

*/ public class ProbingSequence { + private ProbingStep firstStep; - /**Each {@link ProbingSequence} requires a start token to begin running. */ + /** + * Each {@link ProbingSequence} requires a start token to begin running. + */ private Token startToken; public void start() { @@ -41,8 +46,8 @@ public void start() { } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link + * Bootstrap}. */ public static class Builder { @@ -57,33 +62,37 @@ public Builder(Token startToken) { } /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, - * built, and pointed to by the previous {@link ProbingStep} added. + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, built, and pointed to by + * the previous {@link ProbingStep} added. */ public Builder addStep(ProbingStep step) { - if (currentStep == null) + if (currentStep == null) { firstStep = step; - else + } else { currentStep.nextStep(step); + } currentStep = step; return this; } - /** We take special note of the first repeated step. */ + /** + * We take special note of the first repeated step. + */ public Builder markFirstRepeated() { firstRepeatedStep = currentStep; return this; } /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and - * calls private constructor to create {@link ProbingSequence}. + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private + * constructor to create {@link ProbingSequence}. */ public ProbingSequence build() { - if (firstRepeatedStep == null) + if (firstRepeatedStep == null) { firstRepeatedStep = firstStep; + } currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 332a8d0de04..98867c01220 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -17,47 +17,59 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import java.util.function.Consumer; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step - * in {@link ProbingSequence}. + * {@link AutoValue} class that represents generator of actions performed at each step in {@link + * ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. - * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, - * generates a new {@link ProbingAction} to call.

- * + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} + * instances. It then modifies these components on each loop iteration with the consumed {@link + * Token} and from that, generates a new {@link ProbingAction} to call.

*/ @AutoValue public abstract class ProbingStep implements Consumer { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Necessary boolean to inform when to obtain next {@link Token}*/ + /** + * Necessary boolean to inform when to obtain next {@link Token} + */ protected boolean isLastStep = false; private ProbingStep nextStep; - /** Time delay duration between actions. */ + /** + * Time delay duration between actions. + */ abstract Duration duration(); - /** {@link Protocol} type for this step. */ + /** + * {@link Protocol} type for this step. + */ abstract Protocol protocol(); - /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ + /** + * {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. + */ abstract OutboundMessageType messageTemplate(); - /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ + /** + * {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation + * of new channels. + */ abstract Bootstrap bootstrap(); + /** Default {@link AutoValue.Builder} for {@link ProbingStep}. */ @AutoValue.Builder - public static abstract class Builder { + public abstract static class Builder { + public abstract Builder setDuration(Duration value); public abstract Builder setProtocol(Protocol value); @@ -85,7 +97,9 @@ ProbingStep nextStep() { return this.nextStep; } - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ + /** + * Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} + */ private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() @@ -94,29 +108,33 @@ private ProbingAction generateAction(Token token) throws UndeterminedStateExcept .setOutboundMessage(message) .setHost(token.host()); - if (token.channel() != null) + if (token.channel() != null) { probingActionBuilder.setChannel(token.channel()); - else + } else { probingActionBuilder.setBootstrap(bootstrap()); + } return probingActionBuilder.build(); } - /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ + /** + * On the last step, gets the next {@link Token}. Otherwise, uses the same one. + */ private Token generateNextToken(Token token) { return isLastStep ? token.next() : token; } /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the + * action. * * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. * *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

+ * we note an error. Otherwise, if the future marked as finished when the action is completed is + * marked as a success, we note a success. Otherwise, if the cause of failure will either be a + * failure or error.

*/ @Override public void accept(Token token) { @@ -124,18 +142,17 @@ public void accept(Token token) { //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(UndeterminedStateException e) { + } catch (UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - ChannelFuture future; try { //call the generated action future = currentAction.call(); - } catch(Exception e) { + } catch (Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); @@ -144,7 +161,6 @@ public void accept(Token token) { return; } - future.addListener(f -> { if (f.isSuccess()) { //On a successful result, we log as a successful step, and not a success @@ -155,9 +171,10 @@ public void accept(Token token) { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - if (protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token + if (protocol().persistentConnection()) { + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + } //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); @@ -168,8 +185,8 @@ public void accept(Token token) { @Override public final String toString() { - return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n", + return String.format("ProbingStep with Protocol: %s\n" + + "OutboundMessage: %s\n", protocol(), messageTemplate().getClass().getName()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index b430d79507a..676fd80d740 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -26,23 +26,30 @@ @AutoValue public abstract class Protocol { - /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + /** + * {@link AttributeKey} that lets channel reference {@link Protocol} that created it. + */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); public abstract String name(); public abstract int port(); - /** The {@link ChannelHandler} providers to use for the protocol, in order. */ + /** + * The {@link ChannelHandler} providers to use for the protocol, in order. + */ abstract ImmutableList> handlerProviders(); - /** Boolean that notes if connection associated with Protocol is persistent.*/ + /** + * Boolean that notes if connection associated with Protocol is persistent. + */ abstract boolean persistentConnection(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } + /** Default {@link AutoValue.Builder} for {@link Protocol}. */ @AutoValue.Builder public abstract static class Builder { @@ -50,7 +57,8 @@ public abstract static class Builder { public abstract Builder setPort(int num); - public abstract Builder setHandlerProviders(ImmutableList> providers); + public abstract Builder setHandlerProviders( + ImmutableList> providers); public abstract Builder setPersistentConnection(boolean value); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index de041afad38..55fc7cf71a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -36,7 +36,9 @@ import javax.inject.Singleton; import org.joda.time.Duration; -/** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ +/** + * A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. + */ @Module public class WebWhoisModule { @@ -45,23 +47,39 @@ public class WebWhoisModule { private static final String HTTP_PROTOCOL_NAME = "http"; private static final String HTTPS_PROTOCOL_NAME = "https"; - /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + /** + * Standard length of messages used by Proxy. Equates to 0.5 MB. + */ private static final int maximumMessageLengthBytes = 512 * 1024; - /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ + /** + * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. + */ @Qualifier - public @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol { - /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ + } + + /** + * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. + */ @Qualifier - public @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol { + + } - /** Dagger qualifier to provide any WebWhois related bindings. */ + /** + * Dagger qualifier to provide any WebWhois related bindings. + */ @Qualifier - public @interface WebWhoisProtocol {} + public @interface WebWhoisProtocol { + + } - /** {@link Provides} standard WebWhois sequence. */ + /** + * {@link Provides} standard WebWhois sequence. + */ @Provides @Singleton @IntoSet @@ -75,7 +93,9 @@ ProbingSequence provideWebWhoisSequence( } - /** {@link Provides} only step used in WebWhois sequence. */ + /** + * {@link Provides} only step used in WebWhois sequence. + */ @Provides @WebWhoisProtocol static ProbingStep provideWebWhoisStep( @@ -92,7 +112,9 @@ static ProbingStep provideWebWhoisStep( .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ + /** + * {@link Provides} the {@link Protocol} that corresponds to http connection. + */ @Singleton @Provides @HttpWhoisProtocol @@ -107,7 +129,9 @@ static Protocol provideHttpWhoisProtocol( .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ + /** + * {@link Provides} the {@link Protocol} that corresponds to https connection. + */ @Singleton @Provides @HttpsWhoisProtocol @@ -123,7 +147,10 @@ static Protocol provideHttpsWhoisProtocol( } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ + /** + * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http + * protocol. + */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( @@ -138,11 +165,15 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ + /** + * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https + * protocol. + */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( - @HttpsWhoisProtocol Provider> sslClientInitializerProvider, + @HttpsWhoisProtocol + Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, Provider messageHandlerProvider, @@ -165,20 +196,25 @@ static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int ma return new HttpObjectAggregator(maxContentLength); } - /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + /** + * {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. + */ @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + static SslClientInitializer provideSslClientInitializer( + SslProvider sslProvider) { return new SslClientInitializer<>(sslProvider); } - /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + /** + * {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. + */ @Singleton @Provides @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClazz){ + Class channelClazz) { return new Bootstrap() .group(eventLoopGroup) .channel(channelClazz); @@ -190,12 +226,14 @@ int provideMaximumMessageLengthBytes() { return maximumMessageLengthBytes; } - /** {@link Provides} the list of top level domains to be probed */ + /** + * {@link Provides} the list of top level domains to be probed + */ @Singleton @Provides @WebWhoisProtocol ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); + return ImmutableList.of("how", "soy", "xn--q9jyb4c"); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index adb833ec629..776a231d6dd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,8 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when - * the action performed failed due to an issue in the connection with the server. + * Subclass of {@link UndeterminedStateException} that represents all instances when the action + * performed failed due to an issue in the connection with the server. */ public class ConnectionException extends UndeterminedStateException { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java index c155d695c7f..d7127717d52 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java @@ -15,9 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails - * before we can determine the state of the result, meaning the status - * is recorded as ERROR. + * Base exception class for all instances when the action performed fails before we can determine + * the state of the result, meaning the status is recorded as ERROR. */ public class UndeterminedStateException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 6b6dad914a4..6552bca3eca 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -16,28 +16,30 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; /** - *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline + * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType + * >}, as it should only be passed in messages that implement the {@link InboundMessageType} + * interface.

* - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error. If the error is an instance of a {@link FailureException} {@code finished} is - * marked as a failure with cause {@link FailureException}. If it is any other type of error, it - * is treated as an {@link UndeterminedStateException} and {@code finished} set as a failure with - * the same cause as what caused the exception. Lastly, if no error is thrown, we know the action - * completed as a success, and, as such, we mark {@code finished} as a success.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a + * {@link + * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this + * channel is informed of the error. If the error is an instance of a {@link FailureException} + * {@code finished} is marked as a failure with cause {@link FailureException}. If it is any other + * type of error, it is treated as an {@link UndeterminedStateException} and {@code finished} set as + * a failure with the same cause as what caused the exception. Lastly, if no error is thrown, we + * know the action completed as a success, and, as such, we mark {@code finished} as a success.

* *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ @@ -45,22 +47,30 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler privateKeySupplier, Supplier certificateSupplier) { + public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, + Supplier certificateSupplier) { //We use the default trust store here as well, setting trustCertificates to null this(sslProvider, null, privateKeySupplier, certificateSupplier); } @@ -99,8 +98,10 @@ protected void initChannel(C channel) throws Exception { SslContextBuilder.forClient() .sslProvider(sslProvider) .trustManager(trustedCertificates); - if (privateKeySupplier != null && certificateSupplier != null) - sslContextBuilder = sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get()); + if (privateKeySupplier != null && certificateSupplier != null) { + sslContextBuilder = sslContextBuilder + .keyManager(privateKeySupplier.get(), certificateSupplier.get()); + } SslHandler sslHandler = sslContextBuilder .build() diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index de20c6b9269..c0f7ce8ae78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,17 +14,15 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; @@ -38,10 +36,11 @@ import org.joda.time.Duration; /** - *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection - * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

+ *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response + * implies a redirection it follows the redirection until either an Error Response is received, or + * {@link HttpResponseStatus.OK} is received

*/ public class WebWhoisActionHandler extends ActionHandler { @@ -49,16 +48,24 @@ public class WebWhoisActionHandler extends ActionHandler { /** Dagger injected components necessary for redirect responses: */ - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + /** + * {@link Bootstrap} necessary for remaking connection on redirect response. + */ private final Bootstrap bootstrap; - /** {@link Protocol} for when redirected to http endpoint. */ + /** + * {@link Protocol} for when redirected to http endpoint. + */ private final Protocol httpWhoisProtocol; - /** {@link Protocol} for when redirected to https endpoint. */ + /** + * {@link Protocol} for when redirected to https endpoint. + */ private final Protocol httpsWhoisProtocol; - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + /** + * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. + */ private final HttpRequestMessage requestMessage; @Inject @@ -76,9 +83,10 @@ public WebWhoisActionHandler( /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, + * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a + * response indicating a Failure, or receives a redirection response, where it follows the + * redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) @@ -101,13 +109,17 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException( + "Redirected Location was invalid. Given Location was: " + response.headers() + .get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, url.getDefaultPort(), newPath)); + logger.atInfo().log(String + .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, + url.getDefaultPort(), newPath)); //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; @@ -116,7 +128,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new FailureException("Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); + throw new FailureException( + "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -141,10 +154,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atWarning().log("Channel was unsuccessfully closed."); } - //Once channel is closed, establish new connection to redirected host, and repeat same actions + //Once channel is closed, establish new connection to redirected host, and repeat + // same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + //Once we have a successful call, set original ChannelPromise as success to tell + // ProbingStep we can move on secondFuture.addListener(f2 -> { if (f2.isSuccess()) { super.channelRead0(ctx, msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 58c395ad86e..576d6a04d42 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -24,25 +24,32 @@ import javax.inject.Inject; /** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} - * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection. + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom + * type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for + * redirection. */ public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject - public WebWhoisMessageHandler() {} + public WebWhoisMessageHandler() { + } - /** Retains {@link HttpRequestMessage} and calls super write method. */ + /** + * Retains {@link HttpRequestMessage} and calls super write method. + */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) + throws Exception { HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ + /** + * Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link + * InboundMessageType} instance. + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8d285811e0d..92e43501438 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -26,8 +26,8 @@ * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. * *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

+ * that modifies the request to reflect the new host and optional path. We also implement a {@code + * name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { @@ -39,7 +39,9 @@ public HttpRequestMessage() { private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, + ByteBuf content) { super(httpVersion, method, uri, content); } @@ -50,19 +52,24 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ + /** + * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} + */ public HttpRequestMessage(FullHttpRequest request) { this(request.protocolVersion(), request.method(), request.uri(), request.content()); request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } - /** Modifies headers to reflect new host and new path if applicable. */ + /** + * Modifies headers to reflect new host and new path if applicable. + */ @Override public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { if (args.length == 1 || args.length == 2) { headers().set("host", args[0]); - if (args.length == 2) + if (args.length == 2) { setUri(args[1]); + } return this; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index f1b2d6ac6a7..7d2ff722076 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -29,8 +29,10 @@ private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, Byte super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { + /** + * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} + */ + public HttpResponseMessage(FullHttpResponse response) { this(response.protocolVersion(), response.status(), response.content()); response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 578526933ba..1d686e4ec34 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -17,4 +17,6 @@ /** * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ -public interface InboundMessageType {} +public interface InboundMessageType { + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 6e3da3f69d2..e435ae59f86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -21,10 +21,16 @@ */ public interface OutboundMessageType { - /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + /** + * All {@link OutboundMessageType} implementing classes should be able to be modified by token + * with String arguments + */ OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; - /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + /** + * Necessary to inform metrics collector what kind of message is sent down {@link + * io.netty.channel.ChannelPipeline} + */ @Override String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dab5851e8d8..b10c45dae8a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,19 +14,19 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.ProbingSequence; import google.registry.monitoring.blackbox.ProbingStep; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} - * in a single loop of a {@link ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} in a single loop of a + * {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes - * on channel that remains unchanged within a loop of the sequence.

+ * in a {@link ProbingSequence}. Additionally, passes on channel that remains unchanged within a + * loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop * in the sequence.

@@ -34,27 +34,38 @@ public abstract class Token { /** - * {@link Channel} that always starts out as null. Once a persistent connection - * is made (such as EPP), that channel is stored in the token and passed on to - * later steps in the sequence until a new loop begins. + * {@link Channel} that always starts out as null. Once a persistent connection is made (such as + * EPP), that channel is stored in the token and passed on to later steps in the sequence until a + * new loop begins. */ protected Channel channel; - /** Obtains next {@link Token} for next loop in sequence. */ + /** + * Obtains next {@link Token} for next loop in sequence. + */ public abstract Token next(); - /** String corresponding to host that is relevant for loop in sequence. */ + /** + * String corresponding to host that is relevant for loop in sequence. + */ public abstract String host(); - /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; + /** + * Modifies the {@link OutboundMessageType} in the manner necessary for each loop + */ + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) + throws UndeterminedStateException; - /** Set method for {@code channel} */ + /** + * Set method for {@code channel} + */ public void setChannel(Channel channel) { this.channel = channel; } - /** Get method for {@code channel}. */ + /** + * Get method for {@code channel}. + */ public Channel channel() { return this.channel; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index bb06ee89db6..3ff852f3556 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -19,26 +19,30 @@ import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import java.util.Iterator; -import java.util.LinkedList; import javax.inject.Inject; -import javax.inject.Named; /** * {@link Token} subtype designed for WebWhois sequence. * *

Between loops of a WebWhois sequence the only thing changing is the tld we - * are probing. As a result, we maintain the list of {@code topLevelDomains} and - * on each call to next, have our index looking at the next {@code topLevelDomain}.

+ * are probing. As a result, we maintain the list of {@code topLevelDomains} and on each call to + * next, have our index looking at the next {@code topLevelDomain}.

*/ public class WebWhoisToken extends Token { - /** For each top level domain (tld), we probe "prefix.tld". */ - private final static String PREFIX = "whois.nic."; + /** + * For each top level domain (tld), we probe "prefix.tld". + */ + private static final String PREFIX = "whois.nic."; - /** {@link ImmutableList} of all top level domains to be probed. */ + /** + * {@link ImmutableList} of all top level domains to be probed. + */ private final Iterator topLevelDomainsIterator; - /** Current index of {@code topLevelDomains} that represents tld we are probing. */ + /** + * Current index of {@code topLevelDomains} that represents tld we are probing. + */ private String currentDomain; @Inject @@ -48,20 +52,28 @@ public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { currentDomain = topLevelDomainsIterator.next(); } - /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ + /** + * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. + */ @Override public WebWhoisToken next() { currentDomain = topLevelDomainsIterator.next(); return this; } - /** Modifies message to reflect the new host coming from the new top level domain. */ + /** + * Modifies message to reflect the new host coming from the new top level domain. + */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + public OutboundMessageType modifyMessage(OutboundMessageType original) + throws UndeterminedStateException { return original.modifyMessage(host()); } - /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ + /** + * Returns host as the concatenation of fixed {@code prefix} and current value of {@code + * topLevelDomains}. + */ @Override public String host() { return PREFIX + currentDomain; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index f7857dd80f9..6cfb235d97c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -43,14 +43,16 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; + /** * Unit tests for {@link ProbingAction} subtypes * *

Attempts to test how well each {@link ProbingAction} works with an {@link ActionHandler} * subtype when receiving to all possible types of responses

- * */ + */ @RunWith(JUnit4.class) public class ProbingActionTest { + private static final String TEST_MESSAGE = "MESSAGE_TEST"; private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; @@ -59,14 +61,19 @@ public class ProbingActionTest { private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ + /** + * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on + * {@link ProbingAction} + */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); private Provider testHandlerProvider = () -> testHandler; private Provider conversionHandlerProvider = () -> conversionHandler; - /** Used for testing how well probing step can create connection to blackbox server */ + /** + * Used for testing how well probing step can create connection to blackbox server + */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); @@ -152,10 +159,10 @@ public void testSuccess_newChannel() throws Exception { //Tests to see if message is properly sent to remote server nettyRule.assertReceivedMessage(TEST_MESSAGE); - future.syncUninterruptibly(); + future = future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler) testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 1f09dd13553..307d19221dd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -48,29 +48,39 @@ import org.junit.Test; import org.mockito.Mockito; -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +/** + * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific + * implementations + */ public class ProbingStepTest { - /** Basic Constants necessary for tests */ - private final static String ADDRESS_NAME = "TEST_ADDRESS"; - private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final static int PROTOCOL_PORT = 0; - private final static String TEST_MESSAGE = "TEST_MESSAGE"; - private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + /** + * Basic Constants necessary for tests + */ + private static final String ADDRESS_NAME = "TEST_ADDRESS"; + private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private static final int PROTOCOL_PORT = 0; + private static final String TEST_MESSAGE = "TEST_MESSAGE"; + private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private static final LocalAddress ADDRESS = new LocalAddress(ADDRESS_NAME); private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); - /** Used for testing how well probing step can create connection to blackbox server */ + /** + * Used for testing how well probing step can create connection to blackbox server + */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + /** + * The two main handlers we need in any test pipeline used that connects to {@link NettyRule's + * server} + **/ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); @@ -119,7 +129,7 @@ public void testNewChannel() throws Exception { Token testToken = new NewChannelToken(ADDRESS_NAME); //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(address); + nettyRule.setUpServer(ADDRESS); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -179,7 +189,8 @@ public void testWithSequence_ExistingChannel() throws Exception { assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + //Call accept on the first step, which should send our message through the EmbeddedChannel + // pipeline firstStep.accept(testToken); Object msg = channel.readOutbound(); @@ -188,7 +199,7 @@ public void testWithSequence_ExistingChannel() throws Exception { msg = channel.readOutbound(); } //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + assertThat(((ByteBuf) channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java deleted file mode 100644 index 46615a506fb..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; - -import com.google.common.collect.ImmutableList; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; -import io.netty.channel.nio.NioEventLoopGroup; - -/** - * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform - */ -public abstract class TestServer { - - TestServer(LocalAddress localAddress, ImmutableList handlers) { - this(new NioEventLoopGroup(1), localAddress, handlers); - } - - TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - //Creates ChannelInitializer with handlers specified - ChannelInitializer serverInitializer = new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) { - for (ChannelHandler handler : handlers) { - ch.pipeline().addLast(handler); - } - } - }; - //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using LocalServerChannel class - ServerBootstrap serverBootstrap = - new ServerBootstrap() - .group(eventLoopGroup) - .channel(LocalServerChannel.class) - .childHandler(serverInitializer); - - ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java deleted file mode 100644 index 28b36190a7e..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; - -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandler.Sharable; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.local.LocalAddress; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpServerCodec; - -/** - * {@link TestServer} subtype that performs WebWhois Services Expected - * - *

It will either redirect the client to the correct location if given the - * requisite redirect input, give the client a successful response if they give - * the expected final destination, or give the client an error message if given - * an unexpected host location

- */ -public class WebWhoisServer extends TestServer { - - public WebWhoisServer(LocalAddress localAddress, ImmutableList handlers) { - super(localAddress, handlers); - } - - public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - super(eventLoopGroup, localAddress, handlers); - } - - /** Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the HttpRequestMessage object through pipeline */ - public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { - return new WebWhoisServer( - eventLoopGroup, - localAddress, - ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) - ); - } - /** Creates server that sends exactly what we expect a remote server to send as a response, by sending the {@link ByteBuf} of the response through pipeline */ - public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { - return new WebWhoisServer( - eventLoopGroup, - localAddress, - ImmutableList.of( - new HttpServerCodec(), - new HttpObjectAggregator(1048576), - new RedirectHandler(redirectInput, destinationInput)) - ); - } - - /** - * Handler that will wither redirect client, give successful response, or give error messge - */ - @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { - private String redirectInput; - private String destinationInput; - - /** - * - * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location - */ - public RedirectHandler(String redirectInput, String destinationInput) { - this.redirectInput = redirectInput; - this.destinationInput = destinationInput; - } - - /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ - @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { - HttpResponse response; - if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); - } else if (request.headers().get("host").equals(destinationInput)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); - } - ctx.channel().writeAndFlush(response); - - } - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 50c60d9fc52..c0c5831a68c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -29,7 +29,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** Utility class for various helper methods used in testing. */ +/** + * Utility class for various helper methods used in testing. + */ public class TestUtils { public static FullHttpRequest makeHttpGetRequest(String host, String path) { @@ -52,7 +54,9 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { return response; } - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + /** + * Creates HttpResponse given status, redirection location, and other necessary inputs + */ public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); @@ -66,13 +70,17 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** Basic outline for {@link Token} instances to be used in tests */ - static abstract class TestToken extends Token { + /** + * Basic outline for {@link Token} instances to be used in tests + */ + abstract static class TestToken extends Token { + protected String host; protected TestToken(String host) { this.host = host; } + @Override public Token next() { return this; @@ -90,29 +98,29 @@ public String host() { } - /** {@link TestToken} instance that creates new channel */ + /** + * {@link TestToken} instance that creates new channel + */ public static class NewChannelToken extends TestToken { + public NewChannelToken(String host) { super(host); } + @Override public Channel channel() { return null; } } - /** {@link TestToken} instance that passes in existing channel */ + /** + * {@link TestToken} instance that passes in existing channel + */ public static class ExistingChannelToken extends TestToken { - private Channel channel; - public ExistingChannelToken(Channel channel, String host) { super(host); this.channel = channel; } - @Override - public Channel channel() { - return channel; - } } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index c9d337d6ad8..987abbfd7dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -28,15 +28,17 @@ import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to - * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link + * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} + * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** Handles inbound conversion */ + /** + * Handles inbound conversion + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; @@ -44,7 +46,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception buf.release(); } - /** Handles outbound conversion */ + /** + * Handles outbound conversion + */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 86b54d9a07d..f51f8c8fd61 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -28,7 +28,7 @@ import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -52,23 +52,24 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest} + *

*/ public final class NettyRule extends ExternalResource { - // All I/O operations are done inside the single thread within this event loop group, which is // different from the main test thread. Therefore synchronizations are required to make sure that // certain I/O activities are finished when assertions are performed. public NettyRule() { eventLoopGroup = new NioEventLoopGroup(1); } + public NettyRule(EventLoopGroup e) { eventLoopGroup = e; } + private final EventLoopGroup eventLoopGroup; - private WebWhoisServer webWhoisServer; // Handler attached to server's channel to record the request received. private EchoHandler echoHandler; @@ -78,16 +79,20 @@ public NettyRule(EventLoopGroup e) { private Channel channel; - /** Sets up a server channel bound to the given local address. */ + /** + * Sets up a server channel bound to the given local address. + */ public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.builder().add(handlers).add(echoHandler).build()); } - /** Sets up a client channel connecting to the give local address. */ + /** + * Sets up a client channel connecting to the give local address. + */ void setUpClient( LocalAddress localAddress, Protocol protocol, @@ -121,7 +126,9 @@ private void checkReady() { checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); } - /** Test that custom setup to send message to current server sends right message */ + /** + * Test that custom setup to send message to current server sends right message + */ public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); @@ -130,9 +137,9 @@ public void assertReceivedMessage(String message) throws Exception { /** * Test that a message can go through, both inbound and outbound. * - *

The client writes the message to the server, which echos it back and saves the string in its - * promise. The client receives the echo and saves it in its promise. All these activities happens - * in the I/O thread, and this call itself returns immediately. + *

The client writes the message to the server, which echos it back and saves the string in + * its promise. The client receives the echo and saves it in its promise. All these activities + * happens in the I/O thread, and this call itself returns immediately. */ void assertThatMessagesWork() throws Exception { checkReady(); @@ -196,7 +203,9 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E } } - /** A handler that dumps its inbound message to a promise that can be inspected later. */ + /** + * A handler that dumps its inbound message to a promise that can be inspected later. + */ private static class DumpHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture responseFuture = new CompletableFuture<>(); @@ -217,7 +226,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception responseFuture.complete(response); } - /** Saves any inbound error into the failure cause of the promise. */ + /** + * Saves any inbound error into the failure cause of the promise. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 523fb228752..25e5608a100 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -62,10 +62,14 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - /** Fake host to test if the SSL engine gets the correct peer host. */ + /** + * Fake host to test if the SSL engine gets the correct peer host. + */ private static final String SSL_HOST = "www.example.tld"; - /** Fake port to test if the SSL engine gets the correct peer port. */ + /** + * Fake port to test if the SSL engine gets the correct peer port. + */ private static final int SSL_PORT = 12345; @Rule @@ -78,20 +82,24 @@ public class SslClientInitializerTest { @Parameters(name = "{0}") public static SslProvider[] data() { return OpenSsl.isAvailable() - ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[] {SslProvider.JDK}; + ? new SslProvider[]{SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[]{SslProvider.JDK}; } - /** Saves the SNI hostname received by the server, if sent by the client. */ + /** + * Saves the SNI hostname received by the server, if sent by the client. + */ private String sniHostReceived; - /** Fake protocol saved in channel attribute. */ - private final static Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + /** + * Fake protocol saved in channel attribute. + */ + private static final Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -166,7 +174,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); @@ -195,7 +203,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 95b06e623d1..19e608c97d2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -20,8 +20,8 @@ import io.netty.channel.ChannelHandlerContext; /** - * Concrete implementation of {@link ActionHandler} that does nothing different from - * parent class other than store and return the {@code inboundMessage} + * Concrete implementation of {@link ActionHandler} that does nothing different from parent class + * other than store and return the {@code inboundMessage} */ public class TestActionHandler extends ActionHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 33eb190a66a..5a0d0908724 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -17,17 +17,16 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; @@ -39,7 +38,6 @@ import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -54,15 +52,10 @@ public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; - private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; - private static final String HTTPS_REDIRECT = "https://"; - private static final String REDIRECT_HOST = "www.example.com"; - private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private static final Duration DEFAULT_DURATION = new Duration(0L); - private final Protocol STANDARD_PROTOCOL = Protocol.builder() + private final Protocol standardProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( null, null, null, null))) .setName("http") @@ -96,8 +89,8 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, - STANDARD_PROTOCOL, - STANDARD_PROTOCOL, + standardProtocol, + standardProtocol, messageTemplate ); actionHandlerProvider = () -> actionHandler; @@ -177,6 +170,7 @@ public void testBasic_responseFailure_badRequest() { assertThat(future.cause() instanceof FailureException).isTrue(); } + @SuppressWarnings("CheckReturnValue") @Test public void testBasic_responseFailure_badURL() { //setup diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index bf5cfc45652..9a3e755364b 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -19,8 +19,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; From 60e5909adece14edfb0b4d6aa64725bbe76a78e5 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 8 Aug 2019 13:42:56 -0400 Subject: [PATCH 213/337] Minor syle fixes after succesful rebase onto master --- .../monitoring/blackbox/ProberModule.java | 22 ++-- .../monitoring/blackbox/ProbingAction.java | 94 +++++++------ .../monitoring/blackbox/ProbingSequence.java | 10 +- .../monitoring/blackbox/ProbingStep.java | 44 +++---- .../monitoring/blackbox/Protocol.java | 30 +++-- .../monitoring/blackbox/WebWhoisModule.java | 86 ++++++------ .../blackbox/handlers/ActionHandler.java | 20 +-- .../handlers/WebWhoisActionHandler.java | 4 +- .../blackbox/messages/HttpRequestMessage.java | 15 ++- .../blackbox/messages/InboundMessageType.java | 3 +- .../messages/OutboundMessageType.java | 3 +- .../blackbox/ProbingActionTest.java | 28 ++-- .../blackbox/ProbingSequenceTest.java | 43 +++--- .../monitoring/blackbox/ProbingStepTest.java | 53 +++----- .../monitoring/blackbox/TestUtils.java | 58 +------- .../blackbox/handlers/NettyRule.java | 38 +++--- .../handlers/SslClientInitializerTest.java | 30 ++--- .../handlers/WebWhoisActionHandlerTest.java | 31 ++--- .../blackbox/testservers/TestServer.java | 68 +++++++++- .../blackbox/testservers/WebWhoisServer.java | 124 ------------------ 20 files changed, 324 insertions(+), 480 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index df8b5fdbabd..e5a71636173 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -40,6 +40,17 @@ public class ProberModule { */ private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); + /** + * {@link Provides} the {@link SslProvider} used by instances of {@link + * google.registry.monitoring.blackbox.handlers.SslClientInitializer} + */ + @Provides + @Singleton + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + } + /** * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @@ -68,17 +79,6 @@ Duration provideDuration() { return DEFAULT_DURATION; } - /** - * {@link Provides} the {@link SslProvider} used by instances of {@link - * google.registry.monitoring.blackbox.handlers.SslClientInitializer} - */ - @Provides - @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; - } - /** * Root level {@link Component} that provides each {@link ProbingSequence}. */ diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index cdb099e4a76..8173ba6baee 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -42,7 +42,6 @@ import java.net.UnknownHostException; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -67,26 +66,42 @@ @AutoValue public abstract class ProbingAction implements Callable { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when * channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey .valueOf("CONNECTION_FUTURE_KEY"); - /** * {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey .valueOf("REMOTE_ADDRESS_KEY"); - + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** * {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); + } + + /** + * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified + * + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified + */ + private static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); + } + } + /** * Actual {@link Duration} of this delay */ @@ -101,7 +116,6 @@ public abstract class ProbingAction implements Callable { * {@link Channel} object that either created by or passed into this {@link ProbingAction} * instance */ - @Nullable public abstract Channel channel(); /** @@ -115,7 +129,7 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** - * Performs the work of the actual action + * Performs the work of the actual action. * *

First, checks if channel is active by setting a listener to perform the bulk of the work * when the connection future is successful.

@@ -130,12 +144,6 @@ public abstract class ProbingAction implements Callable { * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - - - /** - * Method that calls on {@code performAction} when it is certain channel connection is - * established. - */ @Override public ChannelFuture call() { //ChannelPromise that we return @@ -212,6 +220,19 @@ public ChannelFuture call() { return finished; } + @Override + public final String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host() + ); + } /** * {@link AutoValue.Builder} that does work of creating connection when not already present. @@ -245,6 +266,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract ProbingAction autoBuild(); public ProbingAction build() { + // Sets SocketAddress to bind to. SocketAddress address; try { InetAddress hostAddress = InetAddress.getByName(host()); @@ -253,12 +275,20 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel() == null ^ bootstrap == null, + //Sets channel supplied or to be created. + Channel channel; + try { + channel = channel(); + } catch (IllegalStateException e) { + channel = null; + } + + checkArgument(channel == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel() == null) { + if (channel == null) { bootstrap.handler( new ChannelInitializer() { @Override @@ -283,38 +313,4 @@ protected void initChannel(Channel outboundChannel) return autoBuild(); } } - - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); - } - - /** - * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified - * - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified - */ - private static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } - - - @Override - public final String toString() { - return String.format( - "ProbingAction with delay: %d\n" - + "outboundMessage: %s\n" - + "protocol: %s\n" - + "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 175cf4dcfa5..7f97f8bd519 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -40,6 +40,11 @@ public class ProbingSequence { */ private Token startToken; + private ProbingSequence(ProbingStep firstStep, Token startToken) { + this.firstStep = firstStep; + this.startToken = startToken; + } + public void start() { // calls the first step with startToken; firstStep.accept(startToken); @@ -99,10 +104,5 @@ public ProbingSequence build() { return new ProbingSequence(this.firstStep, this.startToken); } } - - private ProbingSequence(ProbingStep firstStep, Token startToken) { - this.firstStep = firstStep; - this.startToken = startToken; - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 98867c01220..35bb141246a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -44,6 +44,10 @@ public abstract class ProbingStep implements Consumer { protected boolean isLastStep = false; private ProbingStep nextStep; + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } + /** * Time delay duration between actions. */ @@ -65,26 +69,6 @@ public abstract class ProbingStep implements Consumer { */ abstract Bootstrap bootstrap(); - - /** Default {@link AutoValue.Builder} for {@link ProbingStep}. */ - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setDuration(Duration value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setMessageTemplate(OutboundMessageType value); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract ProbingStep build(); - } - - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); - } - void lastStep() { isLastStep = true; } @@ -117,7 +101,6 @@ private ProbingAction generateAction(Token token) throws UndeterminedStateExcept return probingActionBuilder.build(); } - /** * On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ @@ -172,7 +155,7 @@ public void accept(Token token) { } if (protocol().persistentConnection()) { - //If the connection is persistent, we store the channel in the token + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); } @@ -191,6 +174,23 @@ public final String toString() { messageTemplate().getClass().getName()); } + /** + * Default {@link AutoValue.Builder} for {@link ProbingStep}. + */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDuration(Duration value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract ProbingStep build(); + } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 676fd80d740..ea2a6130380 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -31,6 +31,10 @@ public abstract class Protocol { */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + public static Builder builder() { + return new AutoValue_Protocol.Builder(); + } + public abstract String name(); public abstract int port(); @@ -45,11 +49,20 @@ public abstract class Protocol { */ abstract boolean persistentConnection(); - public static Builder builder() { - return new AutoValue_Protocol.Builder(); + @Override + public final String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); } - /** Default {@link AutoValue.Builder} for {@link Protocol}. */ + /** + * Default {@link AutoValue.Builder} for {@link Protocol}. + */ @AutoValue.Builder public abstract static class Builder { @@ -64,15 +77,4 @@ public abstract Builder setHandlerProviders( public abstract Protocol build(); } - - @Override - public final String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 55fc7cf71a9..8365607da40 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -42,56 +42,14 @@ @Module public class WebWhoisModule { - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; private static final String HTTP_PROTOCOL_NAME = "http"; private static final String HTTPS_PROTOCOL_NAME = "https"; - /** * Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; - - - /** - * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. - */ - @Qualifier - public @interface HttpWhoisProtocol { - - } - - /** - * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. - */ - @Qualifier - public @interface HttpsWhoisProtocol { - - } - - /** - * Dagger qualifier to provide any WebWhois related bindings. - */ - @Qualifier - public @interface WebWhoisProtocol { - - } - - /** - * {@link Provides} standard WebWhois sequence. - */ - @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { - - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); - } - + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; /** * {@link Provides} only step used in WebWhois sequence. @@ -146,7 +104,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http * protocol. @@ -220,6 +177,21 @@ static Bootstrap provideBootstrap( .channel(channelClazz); } + /** + * {@link Provides} standard WebWhois sequence. + */ + @Provides + @Singleton + @IntoSet + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { + + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) + .build(); + } + @Provides @WebWhoisProtocol int provideMaximumMessageLengthBytes() { @@ -248,5 +220,29 @@ int provideHttpsWhoisPort() { return HTTPS_WHOIS_PORT; } + /** + * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. + */ + @Qualifier + public @interface HttpWhoisProtocol { + + } + + /** + * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. + */ + @Qualifier + public @interface HttpsWhoisProtocol { + + } + + /** + * Dagger qualifier to provide any WebWhois related bindings. + */ + @Qualifier + public @interface WebWhoisProtocol { + + } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 6552bca3eca..1e1a834231c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -27,19 +27,19 @@ /** * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType - * >}, as it should only be passed in messages that implement the {@link InboundMessageType} + *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler}, + * as it should only be passed in messages that implement the {@link InboundMessageType} * interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a - * {@link - * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this - * channel is informed of the error. If the error is an instance of a {@link FailureException} - * {@code finished} is marked as a failure with cause {@link FailureException}. If it is any other - * type of error, it is treated as an {@link UndeterminedStateException} and {@code finished} set as - * a failure with the same cause as what caused the exception. Lastly, if no error is thrown, we - * know the action completed as a success, and, as such, we mark {@code finished} as a success.

+ * {@link ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has + * been read. Second, with any exception thrown, the connection is closed, and the ProbingAction + * governing this channel is informed of the error. If the error is an instance of a {@link + * FailureException} {@code finished} is marked as a failure with cause {@link FailureException}. If + * it is any other type of error, it is treated as an {@link UndeterminedStateException} and {@code + * finished} set as a failure with the same cause as what caused the exception. Lastly, if no error + * is thrown, we know the action completed as a success, and, as such, we mark {@code finished} as a + * success.

* *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index c0f7ce8ae78..c56c8c7d97c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -101,7 +101,9 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); - } else if (response.headers().get("location") != null) { + } else if (response.status().equals(HttpResponseStatus.MOVED_PERMANENTLY) + || response.status().equals(HttpResponseStatus.FOUND)) { + //TODO - Fix checker to better determine when we have encountered a redirection response. //Obtain url to be redirected to URL url; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 92e43501438..b850cfb3b26 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -46,12 +46,6 @@ private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String ur } - @Override - public HttpRequestMessage setUri(String path) { - super.setUri(path); - return this; - } - /** * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ @@ -60,6 +54,12 @@ public HttpRequestMessage(FullHttpRequest request) { request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } + @Override + public HttpRequestMessage setUri(String path) { + super.setUri(path); + return this; + } + /** * Modifies headers to reflect new host and new path if applicable. */ @@ -77,7 +77,8 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx throw new IllegalArgumentException( String.format( "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + Arrays.toString(args), args.length)); + + " Received %d arguments instead of 2. Received arguments: " + + Arrays.toString(args), args.length)); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 1d686e4ec34..0a584dfa2a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.messages; /** - * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in + * channel pipeline */ public interface InboundMessageType { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index e435ae59f86..4a7c16243cd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -17,7 +17,8 @@ import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** - * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in + * channel pipeline */ public interface OutboundMessageType { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index 6cfb235d97c..df3296438af 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -30,13 +30,11 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Ignore; import org.junit.Rule; @@ -60,7 +58,11 @@ public class ProbingActionTest { private static final int TEST_PORT = 0; private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - + /** + * Used for testing how well probing step can create connection to blackbox server + */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); /** * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on * {@link ProbingAction} @@ -68,26 +70,18 @@ public class ProbingActionTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = () -> testHandler; - private Provider conversionHandlerProvider = () -> conversionHandler; - - /** - * Used for testing how well probing step can create connection to blackbox server - */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - + //TODO - Currently, this test fails to receive outbound messages from the embedded channel, which + // we will fix in a later release. @Ignore @Test - public void testBehavior_existingChannel() { + public void testSuccess_existingChannel() { //setup EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); // Sets up a Protocol corresponding to when a connection exists. Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) @@ -136,13 +130,13 @@ public void testSuccess_newChannel() throws Exception { // Sets up a Protocol corresponding to when a new connection is created. Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(false) .build(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address); // Sets up a ProbingAction with existing channel using test specified attributes. ProbingAction action = ProbingAction.builder() diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 5c4452df7b3..02599bcb51a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -16,10 +16,12 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import google.registry.monitoring.blackbox.tokens.Token; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -28,30 +30,30 @@ @RunWith(JUnit4.class) public class ProbingSequenceTest { + private ProbingStep firstStep; + private ProbingStep secondStep; + private ProbingStep thirdStep; - private ProbingStep setupMock() { + private Token testToken; + + private ProbingStep setupMockStep() { ProbingStep mock = Mockito.mock(ProbingStep.class); doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); doCallRealMethod().when(mock).nextStep(); return mock; } - private static class Wrapper { - - T data; + @Before + public void setup() { + firstStep = setupMockStep(); + secondStep = setupMockStep(); + thirdStep = setupMockStep(); - public Wrapper(T data) { - this.data = data; - } + testToken = Mockito.mock(Token.class); } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) @@ -63,21 +65,13 @@ public void testSequenceBasicConstruction_Success() { assertThat(secondStep.nextStep()).isEqualTo(thirdStep); assertThat(thirdStep.nextStep()).isEqualTo(firstStep); - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); - sequence.start(); - assertThat(wrapper.data).isTrue(); + verify(firstStep, times(1)).accept(testToken); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(thirdStep) @@ -90,12 +84,9 @@ public void testSequenceAdvancedConstruction_Success() { assertThat(secondStep.nextStep()).isEqualTo(firstStep); assertThat(thirdStep.nextStep()).isEqualTo(secondStep); - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); - sequence.start(); - assertThat(wrapper.data).isTrue(); + verify(thirdStep, times(1)).accept(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 307d19221dd..db7ec271956 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -19,17 +19,18 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; @@ -41,7 +42,6 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Ignore; import org.junit.Rule; @@ -85,26 +85,22 @@ public class ProbingStepTest { private ChannelHandler conversionHandler = new ConversionHandler(); /** - * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} - * is called, it just marks the supplied future as succeeded, returning the requisite token. + * Creates mock {@link Token} object that returns the host and returns unchanged message when + * modifying it. */ - private ProbingStep dummyStep() { - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(dummyStep).nextStep(); - return dummyStep; + private Token testToken(String host) throws UndeterminedStateException { + Token token = Mockito.mock(Token.class); + doReturn(host).when(token).host(); + doAnswer(answer -> answer.getArgument(0)).when(token) + .modifyMessage(any(OutboundMessageType.class)); + return token; } - @Test public void testNewChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - // Sets up Protocol for when we create a new channel. Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) @@ -119,21 +115,19 @@ public void testNewChannel() throws Exception { .build(); //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); // Sets up testToken to return arbitrary values, and no channel. Used when we create a new // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); + Token testToken = testToken(ADDRESS_NAME); //Set up blackbox server that receives our messages then echoes them back to us nettyRule.setUpServer(ADDRESS); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step @@ -146,16 +140,14 @@ public void testNewChannel() throws Exception { verify(dummyStep, times(1)).accept(any(Token.class)); } + //TODO - Currently, this test fails to receive outbound messages from the embedded channel, which + // we will fix in a later release. @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - // Sets up Protocol for when a channel already exists. Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(true) @@ -170,10 +162,9 @@ public void testWithSequence_ExistingChannel() throws Exception { .build(); //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); // Sets up an embedded channel to contain the two handlers we created already. EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); @@ -183,11 +174,11 @@ public void testWithSequence_ExistingChannel() throws Exception { // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, ""); + Token testToken = testToken(""); + doReturn(channel).when(testToken).channel(); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); //Call accept on the first step, which should send our message through the EmbeddedChannel // pipeline @@ -207,7 +198,5 @@ public void testWithSequence_ExistingChannel() throws Exception { //At this point, we should have received the message, so the future obtained should be marked // as a success verify(dummyStep, times(1)).accept(any(Token.class)); - - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index c0c5831a68c..66e2928f45e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,11 +16,8 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -58,7 +55,7 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { * Creates HttpResponse given status, redirection location, and other necessary inputs */ public static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + HttpResponseStatus status, String location, boolean keepAlive) { FullHttpResponse response = makeHttpResponse("", status); response.headers().set("content-type", "text/plain"); if (location != null) { @@ -69,58 +66,5 @@ public static FullHttpResponse makeRedirectResponse( } return response; } - - /** - * Basic outline for {@link Token} instances to be used in tests - */ - abstract static class TestToken extends Token { - - protected String host; - - protected TestToken(String host) { - this.host = host; - } - - @Override - public Token next() { - return this; - } - - @Override - public OutboundMessageType modifyMessage(OutboundMessageType message) { - return message; - } - - @Override - public String host() { - return host; - } - - } - - /** - * {@link TestToken} instance that creates new channel - */ - public static class NewChannelToken extends TestToken { - - public NewChannelToken(String host) { - super(host); - } - - @Override - public Channel channel() { - return null; - } - } - - /** - * {@link TestToken} instance that passes in existing channel - */ - public static class ExistingChannelToken extends TestToken { - public ExistingChannelToken(Channel channel, String host) { - super(host); - this.channel = channel; - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index f51f8c8fd61..4b6eed9c16f 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -28,7 +28,7 @@ import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.testservers.WebWhoisServer; +import google.registry.monitoring.blackbox.testservers.TestServer; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -58,6 +58,13 @@ public final class NettyRule extends ExternalResource { + private final EventLoopGroup eventLoopGroup; + // Handler attached to server's channel to record the request received. + private EchoHandler echoHandler; + // Handler attached to client's channel to record the response received. + private DumpHandler dumpHandler; + private Channel channel; + // All I/O operations are done inside the single thread within this event loop group, which is // different from the main test thread. Therefore synchronizations are required to make sure that // certain I/O activities are finished when assertions are performed. @@ -69,15 +76,10 @@ public NettyRule(EventLoopGroup e) { eventLoopGroup = e; } - private final EventLoopGroup eventLoopGroup; - - // Handler attached to server's channel to record the request received. - private EchoHandler echoHandler; - - // Handler attached to client's channel to record the response received. - private DumpHandler dumpHandler; - - private Channel channel; + private static void writeToChannelAndFlush(Channel channel, String data) { + ChannelFuture unusedFuture = + channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); + } /** * Sets up a server channel bound to the given local address. @@ -86,7 +88,7 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - new WebWhoisServer(eventLoopGroup, localAddress, + new TestServer(eventLoopGroup, localAddress, ImmutableList.builder().add(handlers).add(echoHandler).build()); } @@ -169,6 +171,10 @@ ThrowableSubject assertThatClientRootCause() { assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); } + @Override + protected void after() { + Future unusedFuture = eventLoopGroup.shutdownGracefully(); + } /** * A handler that echoes back its inbound message. The message is also saved in a promise for @@ -234,15 +240,5 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); } } - - @Override - protected void after() { - Future unusedFuture = eventLoopGroup.shutdownGracefully(); - } - - private static void writeToChannelAndFlush(Channel channel, String data) { - ChannelFuture unusedFuture = - channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 25e5608a100..2a9f9758e09 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -71,12 +71,23 @@ public class SslClientInitializerTest { * Fake port to test if the SSL engine gets the correct peer port. */ private static final int SSL_PORT = 12345; - + /** + * Fake protocol saved in channel attribute. + */ + private static final Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); @Rule public NettyRule nettyRule = new NettyRule(); - @Parameter(0) public SslProvider sslProvider; + /** + * Saves the SNI hostname received by the server, if sent by the client. + */ + private String sniHostReceived; // We do our best effort to test all available SSL providers. @Parameters(name = "{0}") @@ -86,21 +97,6 @@ public static SslProvider[] data() { : new SslProvider[]{SslProvider.JDK}; } - /** - * Saves the SNI hostname received by the server, if sent by the client. - */ - private String sniHostReceived; - - /** - * Fake protocol saved in channel attribute. - */ - private static final Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); - private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { SslContext sslContext = SslContextBuilder.forServer(privateKey, certificate).build(); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 5a0d0908724..a4c2c57dc1a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -26,7 +26,7 @@ import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import google.registry.monitoring.blackbox.testservers.WebWhoisServer; +import google.registry.monitoring.blackbox.testservers.TestServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; @@ -111,10 +111,6 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group, LocalAddress address) { - WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); - } private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); @@ -150,27 +146,26 @@ public void testBasic_responseFailure_badRequest() { setup("", null, false); setupChannel(initialProtocol); - //stores future + // Stores future that informs when action is completed. ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); FullHttpResponse response = new HttpResponseMessage( makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); - //assesses that future listener isn't triggered yet. + // Assesses that future listener isn't triggered yet. assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, but event is not success + // Assesses that listener is triggered, but event is not success assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same + // Ensures that we fail as a result of a FailureException. assertThat(future.cause() instanceof FailureException).isTrue(); } - @SuppressWarnings("CheckReturnValue") @Test public void testBasic_responseFailure_badURL() { //setup @@ -182,7 +177,7 @@ public void testBasic_responseFailure_badURL() { channel.writeOutbound(msg); FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true)); //assesses that future listener isn't triggered yet. assertThat(future.isDone()).isFalse(); @@ -193,8 +188,8 @@ public void testBasic_responseFailure_badURL() { assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); + // Ensures that we fail as a result of a FailureException. + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test @@ -207,19 +202,21 @@ public void testAdvanced_redirect() { setupChannel(initialProtocol); // Initializes LocalAddress with unique String. - String host = TARGET_HOST + System.currentTimeMillis(); - LocalAddress address = new LocalAddress(host); + LocalAddress address = new LocalAddress(TARGET_HOST); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); + // Path that we test WebWhoisActionHandler uses. + String path = "/test"; + // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group, address); + TestServer.webWhoisServer(group, address, "", TARGET_HOST, path); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + host, true, false)); + HTTP_REDIRECT + TARGET_HOST + path, true)); //checks that future has not been set to successful or a failure assertThat(future.isDone()).isFalse(); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java index 744dab17f5e..c39fe554390 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java @@ -14,28 +14,38 @@ package google.registry.monitoring.blackbox.testservers; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; + import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to * perform */ -public abstract class TestServer { +public class TestServer { - TestServer(LocalAddress localAddress, ImmutableList handlers) { + public TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } - TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, + public TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @@ -58,4 +68,56 @@ protected void initChannel(LocalChannel ch) { } + public static TestServer webWhoisServer(EventLoopGroup eventLoopGroup, + LocalAddress localAddress, String redirectInput, String destinationInput, + String destinationPath) { + return new TestServer( + eventLoopGroup, + localAddress, + ImmutableList.of(new RedirectHandler(redirectInput, destinationInput, destinationPath)) + ); + } + + /** + * Handler that will wither redirect client, give successful response, or give error messge + */ + @Sharable + static class RedirectHandler extends SimpleChannelInboundHandler { + + private String redirectInput; + private String destinationInput; + private String destinationPath; + + /** + * @param redirectInput - Server will send back redirect to {@code destinationInput} when + * receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response + * when receiving a request with this host location + */ + public RedirectHandler(String redirectInput, String destinationInput, String destinationPath) { + this.redirectInput = redirectInput; + this.destinationInput = destinationInput; + this.destinationPath = destinationPath; + } + + /** + * Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on + * what header location is + */ + @Override + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { + HttpResponse response; + if (request.headers().get("host").equals(redirectInput)) { + response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true)); + } else if (request.headers().get("host").equals(destinationInput) + && request.uri().equals(destinationPath)) { + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); + } else { + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + } + ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response); + + } + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java deleted file mode 100644 index d15a8a8e3a4..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.testservers; - -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandler.Sharable; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.local.LocalAddress; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpServerCodec; - -/** - * {@link TestServer} subtype that performs WebWhois Services Expected - * - *

It will either redirect the client to the correct location if given the - * requisite redirect input, give the client a successful response if they give the expected final - * destination, or give the client an error message if given an unexpected host location

- */ -public class WebWhoisServer extends TestServer { - - public WebWhoisServer(LocalAddress localAddress, - ImmutableList handlers) { - super(localAddress, handlers); - } - - public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, - ImmutableList handlers) { - super(eventLoopGroup, localAddress, handlers); - } - - /** - * Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the - * HttpRequestMessage object through pipeline - */ - public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, - LocalAddress localAddress, String redirectInput, String destinationInput) { - return new WebWhoisServer( - eventLoopGroup, - localAddress, - ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) - ); - } - - /** - * Creates server that sends exactly what we expect a remote server to send as a response, by - * sending the {@link ByteBuf} of the response through pipeline - */ - public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, - String redirectInput, String destinationInput) { - return new WebWhoisServer( - eventLoopGroup, - localAddress, - ImmutableList.of( - new HttpServerCodec(), - new HttpObjectAggregator(1048576), - new RedirectHandler(redirectInput, destinationInput)) - ); - } - - /** - * Handler that will wither redirect client, give successful response, or give error messge - */ - @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { - - private String redirectInput; - private String destinationInput; - - /** - * @param redirectInput - Server will send back redirect to {@code destinationInput} when - * receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response - * when receiving a request with this host location - */ - public RedirectHandler(String redirectInput, String destinationInput) { - this.redirectInput = redirectInput; - this.destinationInput = destinationInput; - } - - /** - * Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on - * what header location is - */ - @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { - HttpResponse response; - if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, - false)); - } else if (request.headers().get("host").equals(destinationInput)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); - } - ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response); - - } - } -} From fe9531670d36ae39e9adc6f727a8d7d787c68657 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 20 Jun 2019 16:41:30 -0400 Subject: [PATCH 214/337] Initial Commit. --- .../monitoring/blackbox/ActionHandler.java | 5 + .../monitoring/blackbox/ProbingAction.java | 5 + .../monitoring/blackbox/ProbingSequence.java | 5 + .../monitoring/blackbox/ProbingStep.java | 5 + .../monitoring/blackbox/Protocol.java | 5 + .../monitoring/blackbox/TestToken.java | 5 + .../registry/monitoring/blackbox/Token.java | 5 + prober/build.gradle | 30 +- .../blackbox/AutoValue_NewChannelAction.java | 181 +++++++++++ .../blackbox/AutoValue_ProbingAction.java | 118 +++++++ .../blackbox/AutoValue_Protocol.java | 153 +++++++++ .../monitoring/blackbox/ActionHandler.java | 52 +++ .../registry/monitoring/blackbox/Main.java | 8 + .../monitoring/blackbox/NewChannelAction.java | 70 +++++ .../monitoring/blackbox/ProbingAction.java | 295 ++++-------------- .../monitoring/blackbox/ProbingFlows.java | 15 + .../monitoring/blackbox/ProbingSequence.java | 92 +----- .../monitoring/blackbox/ProbingStep.java | 207 +++--------- .../monitoring/blackbox/Protocol.java | 65 ++-- .../monitoring/blackbox/TestToken.java | 28 ++ .../registry/monitoring/blackbox/Token.java | 20 ++ .../monitoring/blackbox/package-info.java | 16 + 22 files changed, 841 insertions(+), 544 deletions(-) create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java create mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java create mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Main.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/package-info.java diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java new file mode 100644 index 00000000000..a4d36657721 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ActionHandler { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java new file mode 100644 index 00000000000..6b26913d425 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingAction { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java new file mode 100644 index 00000000000..9f3617135a4 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingSequence { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java new file mode 100644 index 00000000000..b8b237a1e91 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class ProbingStep { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java new file mode 100644 index 00000000000..75d13b3039a --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class Protocol { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java new file mode 100644 index 00000000000..98f21f8d63a --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class TestToken { + +} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java new file mode 100644 index 00000000000..16f05be0430 --- /dev/null +++ b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java @@ -0,0 +1,5 @@ +package google.registry.monitoring.blackbox; + +public class Token { + +} diff --git a/prober/build.gradle b/prober/build.gradle index 3652390d0ba..33feefb7175 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,30 +1,25 @@ -// Copyright 2019 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. - apply plugin: 'java' -createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') +createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Main') + dependencies { def deps = rootProject.dependencyMap + compile deps['com.beust:jcommander'] + compile deps['com.google.api-client:google-api-client'] + compile deps['com.google.apis:google-api-services-cloudkms'] + compile deps['com.google.apis:google-api-services-monitoring'] + compile deps['com.google.apis:google-api-services-storage'] compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] + compile deps['com.google.http-client:google-http-client'] + compile deps['com.google.monitoring-client:metrics'] + compile deps['com.google.monitoring-client:stackdriver'] compile deps['io.netty:netty-buffer'] compile deps['io.netty:netty-codec-http'] compile deps['io.netty:netty-codec'] @@ -41,10 +36,13 @@ dependencies { runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] + testCompile deps['com.google.monitoring-client:contrib'] testCompile deps['com.google.truth:truth'] + testCompile deps['org.yaml:snakeyaml'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') + testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -52,4 +50,4 @@ dependencies { testAnnotationProcessor deps['com.google.auto.value:auto-value'] annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] -} +} \ No newline at end of file diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java new file mode 100644 index 00000000000..6f818f03a28 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java @@ -0,0 +1,181 @@ + + +package google.registry.monitoring.blackbox; + +import io.netty.bootstrap.Bootstrap; +import javax.annotation.Generated; +import org.joda.time.Duration; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_NewChannelAction extends NewChannelAction { + + private final Duration delay; + + private final O outboundMessage; + + private final Protocol protocol; + + private final ActionHandler actionHandler; + + private final Bootstrap bootstrap; + + private AutoValue_NewChannelAction( + Duration delay, + O outboundMessage, + Protocol protocol, + ActionHandler actionHandler, + Bootstrap bootstrap) { + this.delay = delay; + this.outboundMessage = outboundMessage; + this.protocol = protocol; + this.actionHandler = actionHandler; + this.bootstrap = bootstrap; + } + + @Override + Duration delay() { + return delay; + } + + @Override + O outboundMessage() { + return outboundMessage; + } + + @Override + Protocol protocol() { + return protocol; + } + + @Override + ActionHandler actionHandler() { + return actionHandler; + } + + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + @Override + public String toString() { + return "NewChannelAction{" + + "delay=" + delay + ", " + + "outboundMessage=" + outboundMessage + ", " + + "protocol=" + protocol + ", " + + "actionHandler=" + actionHandler + ", " + + "bootstrap=" + bootstrap + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof NewChannelAction) { + NewChannelAction that = (NewChannelAction) o; + return this.delay.equals(that.delay()) + && this.outboundMessage.equals(that.outboundMessage()) + && this.protocol.equals(that.protocol()) + && this.actionHandler.equals(that.actionHandler()) + && this.bootstrap.equals(that.bootstrap()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= delay.hashCode(); + h$ *= 1000003; + h$ ^= outboundMessage.hashCode(); + h$ *= 1000003; + h$ ^= protocol.hashCode(); + h$ *= 1000003; + h$ ^= actionHandler.hashCode(); + h$ *= 1000003; + h$ ^= bootstrap.hashCode(); + return h$; + } + + static final class Builder extends NewChannelAction.Builder { + private Duration delay; + private O outboundMessage; + private Protocol protocol; + private ActionHandler actionHandler; + private Bootstrap bootstrap; + Builder() { + } + @Override + public NewChannelAction.Builder delay(Duration delay) { + if (delay == null) { + throw new NullPointerException("Null delay"); + } + this.delay = delay; + return this; + } + @Override + public NewChannelAction.Builder outboundMessage(O outboundMessage) { + if (outboundMessage == null) { + throw new NullPointerException("Null outboundMessage"); + } + this.outboundMessage = outboundMessage; + return this; + } + @Override + public NewChannelAction.Builder protocol(Protocol protocol) { + if (protocol == null) { + throw new NullPointerException("Null protocol"); + } + this.protocol = protocol; + return this; + } + @Override + public NewChannelAction.Builder actionHandler(ActionHandler actionHandler) { + if (actionHandler == null) { + throw new NullPointerException("Null actionHandler"); + } + this.actionHandler = actionHandler; + return this; + } + @Override + public NewChannelAction.Builder bootstrap(Bootstrap bootstrap) { + if (bootstrap == null) { + throw new NullPointerException("Null bootstrap"); + } + this.bootstrap = bootstrap; + return this; + } + @Override + public NewChannelAction build() { + String missing = ""; + if (this.delay == null) { + missing += " delay"; + } + if (this.outboundMessage == null) { + missing += " outboundMessage"; + } + if (this.protocol == null) { + missing += " protocol"; + } + if (this.actionHandler == null) { + missing += " actionHandler"; + } + if (this.bootstrap == null) { + missing += " bootstrap"; + } + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing required properties:" + missing); + } + return new AutoValue_NewChannelAction( + this.delay, + this.outboundMessage, + this.protocol, + this.actionHandler, + this.bootstrap); + } + } + +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java new file mode 100644 index 00000000000..26f560b145b --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java @@ -0,0 +1,118 @@ + + +package google.registry.monitoring.blackbox; + +import io.netty.channel.Channel; +import javax.annotation.Generated; +import org.joda.time.Duration; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_ProbingAction extends ProbingAction { + + private final Duration delay; + + private final O outboundMessage; + + private final Channel channel; + + private final Protocol protocol; + + private final ActionHandler actionHandler; + + AutoValue_ProbingAction( + Duration delay, + O outboundMessage, + Channel channel, + Protocol protocol, + ActionHandler actionHandler) { + if (delay == null) { + throw new NullPointerException("Null delay"); + } + this.delay = delay; + if (outboundMessage == null) { + throw new NullPointerException("Null outboundMessage"); + } + this.outboundMessage = outboundMessage; + if (channel == null) { + throw new NullPointerException("Null channel"); + } + this.channel = channel; + if (protocol == null) { + throw new NullPointerException("Null protocol"); + } + this.protocol = protocol; + if (actionHandler == null) { + throw new NullPointerException("Null actionHandler"); + } + this.actionHandler = actionHandler; + } + + @Override + Duration delay() { + return delay; + } + + @Override + O outboundMessage() { + return outboundMessage; + } + + @Override + Channel channel() { + return channel; + } + + @Override + Protocol protocol() { + return protocol; + } + + @Override + ActionHandler actionHandler() { + return actionHandler; + } + + @Override + public String toString() { + return "ProbingAction{" + + "delay=" + delay + ", " + + "outboundMessage=" + outboundMessage + ", " + + "channel=" + channel + ", " + + "protocol=" + protocol + ", " + + "actionHandler=" + actionHandler + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof ProbingAction) { + ProbingAction that = (ProbingAction) o; + return this.delay.equals(that.delay()) + && this.outboundMessage.equals(that.outboundMessage()) + && this.channel.equals(that.channel()) + && this.protocol.equals(that.protocol()) + && this.actionHandler.equals(that.actionHandler()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= delay.hashCode(); + h$ *= 1000003; + h$ ^= outboundMessage.hashCode(); + h$ *= 1000003; + h$ ^= channel.hashCode(); + h$ *= 1000003; + h$ ^= protocol.hashCode(); + h$ *= 1000003; + h$ ^= actionHandler.hashCode(); + return h$; + } + +} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java new file mode 100644 index 00000000000..3247cbdd310 --- /dev/null +++ b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java @@ -0,0 +1,153 @@ + + +package google.registry.monitoring.blackbox; + +import com.google.common.collect.ImmutableList; +import io.netty.channel.ChannelHandler; +import javax.annotation.Generated; +import javax.inject.Provider; + +@Generated("com.google.auto.value.processor.AutoValueProcessor") +final class AutoValue_Protocol extends Protocol { + + private final String name; + + private final int port; + + private final String host; + + private final ImmutableList> handlerProviders; + + private AutoValue_Protocol( + String name, + int port, + String host, + ImmutableList> handlerProviders) { + this.name = name; + this.port = port; + this.host = host; + this.handlerProviders = handlerProviders; + } + + @Override + String name() { + return name; + } + + @Override + int port() { + return port; + } + + @Override + String host() { + return host; + } + + @Override + ImmutableList> handlerProviders() { + return handlerProviders; + } + + @Override + public String toString() { + return "Protocol{" + + "name=" + name + ", " + + "port=" + port + ", " + + "host=" + host + ", " + + "handlerProviders=" + handlerProviders + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Protocol) { + Protocol that = (Protocol) o; + return this.name.equals(that.name()) + && this.port == that.port() + && this.host.equals(that.host()) + && this.handlerProviders.equals(that.handlerProviders()); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= name.hashCode(); + h$ *= 1000003; + h$ ^= port; + h$ *= 1000003; + h$ ^= host.hashCode(); + h$ *= 1000003; + h$ ^= handlerProviders.hashCode(); + return h$; + } + + static final class Builder extends Protocol.Builder { + private String name; + private Integer port; + private String host; + private ImmutableList> handlerProviders; + Builder() { + } + @Override + Protocol.Builder name(String name) { + if (name == null) { + throw new NullPointerException("Null name"); + } + this.name = name; + return this; + } + @Override + Protocol.Builder port(int port) { + this.port = port; + return this; + } + @Override + Protocol.Builder host(String host) { + if (host == null) { + throw new NullPointerException("Null host"); + } + this.host = host; + return this; + } + @Override + Protocol.Builder handlerProviders(ImmutableList> handlerProviders) { + if (handlerProviders == null) { + throw new NullPointerException("Null handlerProviders"); + } + this.handlerProviders = handlerProviders; + return this; + } + @Override + Protocol build() { + String missing = ""; + if (this.name == null) { + missing += " name"; + } + if (this.port == null) { + missing += " port"; + } + if (this.host == null) { + missing += " host"; + } + if (this.handlerProviders == null) { + missing += " handlerProviders"; + } + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing required properties:" + missing); + } + return new AutoValue_Protocol( + this.name, + this.port, + this.host, + this.handlerProviders); + } + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java new file mode 100644 index 00000000000..1437d600539 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java @@ -0,0 +1,52 @@ +// 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.monitoring.blackbox; + +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import java.util.function.Function; + +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { + + private ChannelPromise finished; + private Channel channel; + + @Override + public ChannelFuture apply(O outboundMessage) { + // Send the request to server. + channel.writeAndFlush(outboundMessage); + return finished; + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) { + channel = ctx.channel(); + finished = ctx.newPromise(); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, I InboundMessage) { + // Response received, validate it, register metrics, etc. + // Once everything is done, mark the promise as success; + + finished.setSuccess(); + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java new file mode 100644 index 00000000000..61699ce033c --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java @@ -0,0 +1,8 @@ +package google.registry.monitoring.blackbox; + +public class Main { + public static void main(String[] args) { + System.out.println("Hello, world!"); + + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..ce452e19bf0 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,70 @@ +package google.registry.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOutboundInvoker; +import io.netty.channel.ChannelPromise; +import io.netty.channel.DefaultChannelPromise; +import io.netty.channel.socket.nio.NioSocketChannel; +import org.joda.time.Duration; + +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + abstract Bootstrap bootstrap(); + + private Channel channel; + + @Override + public Channel channel() { + return this.channel; + } + + @Override + public ChannelFuture call() { + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(NioSocketChannel outboundChannel) + throws Exception { + addHandlers( + outboundChannel.pipeline(), protocol().handlerProviders()); + } + }); + + ChannelFuture connectionFuture = bootstrap.connect(protocol().host(), protocol().port()); + ChannelPromise finished = null; + + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + this.channel = channelFuture.channel(); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + + } + } + ); + return finished; + } + + public static ProbingAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder(); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder outboundMessage(O value); + + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 8173ba6baee..2ccf818a57a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,303 +14,126 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; -import io.netty.util.AttributeKey; import io.netty.util.HashedWheelTimer; import io.netty.util.Timer; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; import javax.inject.Provider; -import org.joda.time.Duration; /** - * AutoValue class that represents action generated by {@link ProbingStep} + *Class that represents given action in sequence of probing * - *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when - * the task has been completed

- * - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type - * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall - * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the - * details of that connection.

- * - *

In its build, if there is no channel supplied, it will create a channel from the attributes - * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when - * informed that the connection is successful. If the channel is supplied, the connection future is - * automatically set to successful.

*/ -@AutoValue -public abstract class ProbingAction implements Callable { + +public abstract class ProbingAction implements Callable { /** - * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when - * channel is active. - */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey - .valueOf("CONNECTION_FUTURE_KEY"); - /** - * {@link AttributeKey} in channel that gives the information of the channel's host. - */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey - .valueOf("REMOTE_ADDRESS_KEY"); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** - * {@link Timer} that rate limits probing + * timer that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); - } - /** - * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified - * - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified + * @return actual Duration of delay */ - private static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } + abstract Duration delay(); /** - * Actual {@link Duration} of this delay + * @return message to send to server */ - public abstract Duration delay(); + abstract O outboundMessage(); /** - * {@link OutboundMessageType} instance that we write and flush down pipeline to server + * @return Channel object that represents connection between prober client and server */ - public abstract OutboundMessageType outboundMessage(); + abstract Channel channel(); /** - * {@link Channel} object that either created by or passed into this {@link ProbingAction} - * instance + * @return The Protocol instance that represents action to be tested by this part in sequences */ - public abstract Channel channel(); + abstract Protocol protocol(); /** - * The {@link Protocol} instance that specifies type of connection + * @return The requisite instance of Action Handler, which is always the last Handler in the pipeline */ - public abstract Protocol protocol(); + abstract Bootstrap bootstrap(); + abstract ActionHandler actionHandler(); /** - * The hostname of the remote host we have a connection or will make a connection to + * + * @return Builder for the ProbingAction Class */ - public abstract String host(); /** - * Performs the work of the actual action. - * - *

First, checks if channel is active by setting a listener to perform the bulk of the work - * when the connection future is successful.

- * - *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

- * - *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

- * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. + * The method that calls the ActionHandler to send a message down the channel pipeline + * @return future that denotes when the action has been successfully performed */ @Override public ChannelFuture call() { - //ChannelPromise that we return + // Add the Handlers from the run the action + // (with delay if present), and remove the ActionHandler afterwards, + // in case the channel is to be reused later. + ChannelPromise finished = channel().newPromise(); + timer.newTimeout(timeout -> + // Retry logic may also be added here. + actionHandler().apply(outboundMessage()).addListeners( + future -> finished.setSuccess()), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; + } - //Ensures channel has been set up with connection future as an attribute - checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + abstract static class Builder, P extends ProbingAction> { - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture connectionFuture) -> { - if (connectionFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); + public abstract B delay(Duration value); - ActionHandler actionHandler; - try { - actionHandler = channel().pipeline().get(ActionHandler.class); - } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw - // an UndeterminedStateException - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + public abstract B outboundMessage(O value); - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture unusedFutureWriteAndFlush = - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> { - if (future.isSuccess()) { - ChannelFuture unusedFuture = finished.setSuccess(); - } else { - ChannelFuture unusedFuture = finished.setFailure(future.cause()); - } - }, - //If we don't have a persistent connection, close the connection to this - // channel - future -> { - if (!protocol().persistentConnection()) { + public abstract B protocol(Protocol value); - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) { - logger.atInfo() - .log("Closed stale channel. Moving on to next ProbingStep"); - } else { - logger.atWarning() - .log( - "Could not close channel. Stale connection still exists" - + "."); - } - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(connectionFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } + public abstract B actionHandler(ActionHandler value); - @Override - public final String toString() { - return String.format( - "ProbingAction with delay: %d\n" - + "outboundMessage: %s\n" - + "protocol: %s\n" - + "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); + public abstract P build(); } - /** - * {@link AutoValue.Builder} that does work of creating connection when not already present. + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified */ - @AutoValue.Builder - public abstract static class Builder { - - private Bootstrap bootstrap; - - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; + static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); } + } - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setHost(String value); - - public abstract Builder setChannel(Channel channel); - - abstract Protocol protocol(); - - abstract Channel channel(); - - abstract String host(); - abstract ProbingAction autoBuild(); - public ProbingAction build() { - // Sets SocketAddress to bind to. - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - address = new LocalAddress(host()); - } + /** + * @param channelPipeline is pipeline associated with channel we want to remove handlers from + * removes all handlers from pipeline + */ + static void removeHandlers(ChannelPipeline channelPipeline) { + while (channelPipeline.first() != null) { + channelPipeline.removeFirst(); + } + } - //Sets channel supplied or to be created. - Channel channel; - try { - channel = channel(); - } catch (IllegalStateException e) { - channel = null; - } - checkArgument(channel == null ^ bootstrap == null, - "One and only one of bootstrap and channel must be supplied."); - //If a channel is supplied, nothing is needed to be done - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel == null) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); +} - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } - //now we can actually build the ProbingAction - return autoBuild(); - } - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java new file mode 100644 index 00000000000..73dfd778d69 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox; + +public class ProbingFlows { + + public static void main(String[] args) { + ProbingSequence sequence = new ProbingSequence + .Builder() + .addStep(new ProbingStep()) + .build(); + + sequence.start(); + + + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 7f97f8bd519..7c14d9f0bf0 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -1,77 +1,22 @@ -// Copyright 2019 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.monitoring.blackbox; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.EventLoopGroup; - -/** - * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. - * - * - *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} - * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one - * is the first repeated step.

- * - *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once - * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest - * of the work.

- */ -public class ProbingSequence { - +class ProbingSequence { private ProbingStep firstStep; - /** - * Each {@link ProbingSequence} requires a start token to begin running. - */ - private Token startToken; - - private ProbingSequence(ProbingStep firstStep, Token startToken) { - this.firstStep = firstStep; - this.startToken = startToken; - } - public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + // create a new unique token; + Token token = new TestToken<>(); + firstStep.accept(token); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link - * Bootstrap}. + * Builder that sequentially adds steps */ - public static class Builder { - + static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - - private Token startToken; - public Builder(Token startToken) { - this.startToken = startToken; - } - - /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, built, and pointed to by - * the previous {@link ProbingStep} added. - */ public Builder addStep(ProbingStep step) { - if (currentStep == null) { firstStep = step; } else { @@ -80,29 +25,18 @@ public Builder addStep(ProbingStep step) { currentStep = step; return this; - } - /** - * We take special note of the first repeated step. - */ - public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; - return this; } - /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private - * constructor to create {@link ProbingSequence}. - */ public ProbingSequence build() { - if (firstRepeatedStep == null) { - firstRepeatedStep = firstStep; - } - - currentStep.nextStep(firstRepeatedStep); - currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + currentStep.nextStep(firstStep); + return new ProbingSequence(this.firstStep); } + + } + + private ProbingSequence(ProbingStep firstStep) { + this.firstStep = firstStep; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 35bb141246a..2e2e3575d07 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -1,195 +1,60 @@ -// Copyright 2019 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.monitoring.blackbox; import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import java.util.function.Consumer; -import org.joda.time.Duration; - -/** - * {@link AutoValue} class that represents generator of actions performed at each step in {@link - * ProbingSequence}. - * - *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} - * instances. It then modifies these components on each loop iteration with the consumed {@link - * Token} and from that, generates a new {@link ProbingAction} to call.

- */ -@AutoValue -public abstract class ProbingStep implements Consumer { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * Necessary boolean to inform when to obtain next {@link Token} - */ - protected boolean isLastStep = false; - private ProbingStep nextStep; - - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); - } - /** - * Time delay duration between actions. - */ - abstract Duration duration(); - - /** - * {@link Protocol} type for this step. - */ - abstract Protocol protocol(); - - /** - * {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. - */ - abstract OutboundMessageType messageTemplate(); - - /** - * {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation - * of new channels. - */ - abstract Bootstrap bootstrap(); - - void lastStep() { - isLastStep = true; - } - void nextStep(ProbingStep step) { +public class ProbingStep implements Consumer> { + + private ProbingStep nextStep; + + public void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + public ProbingStep nextStep() { return this.nextStep; } - /** - * Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} - */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { - OutboundMessageType message = token.modifyMessage(messageTemplate()); - ProbingAction.Builder probingActionBuilder = ProbingAction.builder() - .setDelay(duration()) - .setProtocol(protocol()) - .setOutboundMessage(message) - .setHost(token.host()); - - if (token.channel() != null) { - probingActionBuilder.setChannel(token.channel()); - } else { - probingActionBuilder.setBootstrap(bootstrap()); - } - - return probingActionBuilder.build(); - } - /** - * On the last step, gets the next {@link Token}. Otherwise, uses the same one. - */ - private Token generateNextToken(Token token) { - return isLastStep ? token.next() : token; + + private ProbingAction generateAction(Token token) { + // Construct a new ProbingAction and return it. + // The action is only used for one invocation + // and uses the UniqueToken provided in the argument, to + // populate fields in the action. The UniqueToken contains + // all the information needed to create an action, including + // for example the test domain name to be created/deleted and + // the channel to reuse (for ExistingChannelActions). + + return NewChannelAction.builder() + .protocol(token.protocol()) + .outboundMessage(token.message()) + .actionHandler(token.actionHandler()) + .delay(token.DEFAULT_DURATION) + .build(); + } + private Token generateNextToken(Token token) { + // Given the input token, we should be able to deduce what + // this the token for the following steps to use. If this + // step generates an action to create a domain, and the next + // one checks for its existence, the domain contained in the + // token should not change. If this is the last step in a loop + // on the other hand, the next token should contain a new + // domain name for the next loop. + return token.next(); - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the - * action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is completed is - * marked as a success, we note a success. Otherwise, if the cause of failure will either be a - * failure or error.

- */ - @Override - public void accept(Token token) { - ProbingAction currentAction; - //attempt to generate new action. On error, move on to next step - try { - currentAction = generateAction(token); - } catch (UndeterminedStateException e) { - logger.atWarning().withCause(e).log("Error in Action Generation"); - nextStep.accept(generateNextToken(token)); - return; - } - - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch (Exception e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; - } - - future.addListener(f -> { - if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success - logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - - } else { - //On a failed result, we log the failure and note either a failure or error - logger.atSevere().withCause(f.cause()).log("Did not result in future success"); - } - - if (protocol().persistentConnection()) { - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - } - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - - }); } @Override - public final String toString() { - return String.format("ProbingStep with Protocol: %s\n" - + "OutboundMessage: %s\n", - protocol(), - messageTemplate().getClass().getName()); + public void accept(Token token) { + ChannelFuture future = generateAction(token).call(); + future.addListener(f -> nextStep().accept(generateNextToken(token))); } - /** - * Default {@link AutoValue.Builder} for {@link ProbingStep}. - */ - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setDuration(Duration value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setMessageTemplate(OutboundMessageType value); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract ProbingStep build(); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index ea2a6130380..ca18213acf6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -16,65 +16,46 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; import javax.inject.Provider; -/** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. - */ @AutoValue public abstract class Protocol { + final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - /** - * {@link AttributeKey} that lets channel reference {@link Protocol} that created it. - */ - public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - - public static Builder builder() { - return new AutoValue_Protocol.Builder(); - } + /** Protocol name. */ + abstract String name(); - public abstract String name(); + /** Port to bind to at remote host*/ + abstract int port(); - public abstract int port(); + abstract String host(); - /** - * The {@link ChannelHandler} providers to use for the protocol, in order. - */ + /** The {@link ChannelHandler} providers to use for the protocol, in order. */ abstract ImmutableList> handlerProviders(); - /** - * Boolean that notes if connection associated with Protocol is persistent. - */ - abstract boolean persistentConnection(); - - @Override - public final String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); + static Protocol.Builder builder() { + return new AutoValue_Protocol.Builder(); + } + + public static Protocol defaultImplementation(){ + return Protocol.builder().name("Default").port(8080).host("127.0.0.1").handlerProviders(ImmutableList.of()).build(); } - /** - * Default {@link AutoValue.Builder} for {@link Protocol}. - */ @AutoValue.Builder - public abstract static class Builder { + public static abstract class Builder { - public abstract Builder setName(String value); + abstract Builder name(String value); - public abstract Builder setPort(int num); + abstract Builder host(String value); - public abstract Builder setHandlerProviders( - ImmutableList> providers); + abstract Builder port(int num); - public abstract Builder setPersistentConnection(boolean value); + abstract Builder handlerProviders(ImmutableList> providers); - public abstract Protocol build(); + abstract Protocol build(); } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java new file mode 100644 index 00000000000..0fc57f8967e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java @@ -0,0 +1,28 @@ +package google.registry.monitoring.blackbox; + + +public class TestToken extends Token { + @Override + public Protocol protocol(){ + return Protocol.defaultImplementation(); + } + + @Override + public Token next() { + return this; + } + + @Override + public O message() { + return (O) this.domainName; + } + + @Override + public ActionHandler actionHandler() { + return new ActionHandler(); + } + + public static TestToken generateNext() { + return new TestToken(); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java new file mode 100644 index 00000000000..c20ed770888 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java @@ -0,0 +1,20 @@ +package google.registry.monitoring.blackbox; + +import org.joda.time.Duration; + +abstract class Token { + public static final Duration DEFAULT_DURATION = new Duration(2000L); + protected String domainName; + + abstract Protocol protocol(); + abstract Token next(); + abstract O message(); + abstract ActionHandler actionHandler(); + + private static String newDomainName(String previousName) { + return String.format("prober-%d", System.currentTimeMillis()); + } + + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java new file mode 100644 index 00000000000..b3d22bfd24d --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java @@ -0,0 +1,16 @@ +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package google.registry.monitoring.blackbox; \ No newline at end of file From b88d1c3f51414faba3e3df40bd4ca82f62ec17ee Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 24 Jun 2019 12:18:55 -0400 Subject: [PATCH 215/337] Added Protocol Class and its Basic Unit Tests --- .../monitoring/blackbox/ActionHandler.java | 52 ---------- .../monitoring/blackbox/Protocol.java | 26 +++-- .../blackbox/handlers/ActionHandler.java | 95 ++++--------------- .../monitoring/blackbox/TestProtocol.java | 70 ++++++++++++++ 4 files changed, 107 insertions(+), 136 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java deleted file mode 100644 index 1437d600539..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -// 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.monitoring.blackbox; - -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import java.util.function.Function; - -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { - - private ChannelPromise finished; - private Channel channel; - - @Override - public ChannelFuture apply(O outboundMessage) { - // Send the request to server. - channel.writeAndFlush(outboundMessage); - return finished; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) { - channel = ctx.channel(); - finished = ctx.newPromise(); - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, I InboundMessage) { - // Response received, validate it, register metrics, etc. - // Once everything is done, mark the promise as success; - - finished.setSuccess(); - } - -} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index ca18213acf6..3ddecba5af7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -22,26 +22,40 @@ @AutoValue public abstract class Protocol { - final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - /** Protocol name. */ + /** + * Default names associated with each protocol + */ + final static String EPP_PROTOCOL_NAME = "EPP"; + final static String DNS_PROTOCOL_NAME = "DNS"; + final static String WHOIS_PROTOCOL_NAME = "WHOIS"; + final static String RDAP_PROTOCOL_NAME = "RDAP"; + + final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + public boolean PERSISTENT_CONNECTION = name() == EPP_PROTOCOL_NAME; + /** + * @return name of Protocol. + */ abstract String name(); - /** Port to bind to at remote host*/ + /** + * @return Port to bind to at remote host + */ abstract int port(); + /** + * @return hostname to connect to + */ abstract String host(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ abstract ImmutableList> handlerProviders(); + /** Builds new Protocol from @AutoValue Builder implementation*/ static Protocol.Builder builder() { return new AutoValue_Protocol.Builder(); } - public static Protocol defaultImplementation(){ - return Protocol.builder().name("Default").port(8080).host("127.0.0.1").handlerProviders(ImmutableList.of()).build(); - } @AutoValue.Builder public static abstract class Builder { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 1e1a834231c..21797cce800 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. @@ -14,100 +14,39 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; +import java.util.function.Function; -/** - * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline - * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler}, - * as it should only be passed in messages that implement the {@link InboundMessageType} - * interface.

- * - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a - * {@link ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has - * been read. Second, with any exception thrown, the connection is closed, and the ProbingAction - * governing this channel is informed of the error. If the error is an instance of a {@link - * FailureException} {@code finished} is marked as a failure with cause {@link FailureException}. If - * it is any other type of error, it is treated as an {@link UndeterminedStateException} and {@code - * finished} set as a failure with the same cause as what caused the exception. Lastly, if no error - * is thrown, we know the action completed as a success, and, as such, we mark {@code finished} as a - * success.

- * - *

Subclasses specify further work to be done for specific kinds of channel pipelines.

- */ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +public class ActionHandler extends SimpleChannelInboundHandler + implements Function { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link ChannelPromise} that informs {@link ProbingAction} if response has been received. - */ private ChannelPromise finished; + private Channel channel; - /** - * Returns initialized {@link ChannelPromise} to {@link ProbingAction}. - */ - public ChannelFuture getFinishedFuture() { + @Override + public ChannelFuture apply(O outboundMessage) { + // Send the request to server. + channel.writeAndFlush(outboundMessage); return finished; } - /** - * Initializes {@link ChannelPromise} - */ @Override public void handlerAdded(ChannelHandlerContext ctx) { - //Once handler is added to channel pipeline, initialize channel and future for this handler + channel = ctx.channel(); finished = ctx.newPromise(); } - /** - * Marks {@link ChannelPromise} as success - */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + protected void channelRead0(ChannelHandlerContext ctx, I InboundMessage) { + // Response received, validate it, register metrics, etc. + // Once everything is done, mark the promise as success; - ChannelFuture unusedFuture = finished.setSuccess(); + finished.setSuccess(); } - /** - * Logs the channel and pipeline that caused error, closes channel, then informs {@link - * ProbingAction} listeners of error. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atWarning().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); - - if (cause instanceof FailureException) { - //On FailureException, we know the response is a failure. - - //Since it wasn't a success, we still want to log to see what caused the FAILURE - logger.atInfo().log(cause.getMessage()); - - //As always, inform the ProbingStep that we successfully completed this action - ChannelFuture unusedFuture = finished.setFailure(cause); - - } else { - //On UndeterminedStateException, we know the response type is an error. - - //Since it wasn't a success, we still log what caused the ERROR - logger.atWarning().log(cause.getMessage()); - ChannelFuture unusedFuture = finished.setFailure(cause); - - //As this was an ERROR in performing the action, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } - } } + diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java new file mode 100644 index 00000000000..8f35843cb4c --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java @@ -0,0 +1,70 @@ +package google.registry.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.TestModule.TestProtocolModule; +import google.registry.monitoring.blackbox.TestModule.TestComponent; +import com.google.common.collect.ImmutableList; +import io.netty.channel.ChannelHandler; +import javax.inject.Inject; +import javax.inject.Provider; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Basic unit test for Protocol Class + */ +@RunWith(JUnit4.class) +public class TestProtocol { + + /** + * Stores default values that constitute a Protocol + */ + private static final String HOST_NAME = "127.0.0.1"; + private static final int PORT_NUM = 0; + private static final String NAME = "Test"; + private static final ImmutableList> HANDLERS = ImmutableList.of(); + + /** + * Test Protocol that we build + */ + private Protocol protocol; + + /** + * + * @return Protocol implementation built using fields above + */ + static Protocol defaultImplementation() { + return Protocol.builder() + .host(HOST_NAME) + .port(PORT_NUM) + .name(NAME) + .handlerProviders(HANDLERS) + .build(); + } + + /** + * Stores default implementation into private protocol field + */ + private void basicProtocol() { + protocol = TestProtocol.defaultImplementation(); + } + + + /** + * Basic unit test that insures stored values in protocol are accurate + */ + @Test + public void testProtocolAttributes() { + basicProtocol(); + assertThat(protocol.host()).isEqualTo(HOST_NAME); + assertThat(protocol.port()).isEqualTo(PORT_NUM); + assertThat(protocol.name()).isEqualTo(NAME); + assertThat(protocol.handlerProviders()).isEqualTo(HANDLERS); + } + + + +} From 79d35fa688e3ed3b10c5d349a9b8982639bf4638 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:06:18 -0400 Subject: [PATCH 216/337] Fixed Gitignore to take out AutoValue generated code --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 327b22fe2e7..199c4fe3979 100644 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,9 @@ nomulus.iws # Javascript output **/out/* +# AutoValue generated code +AutoValue_.*.java + ###################################################################### # Python Ignores From f2635d337658f950f280610efbec29e1f0be56fd Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 1 Jul 2019 13:30:57 -0400 Subject: [PATCH 217/337] Final Changes in .gitignore --- prober/.gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index c86568e7672..89f9ac04aac 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From b845092d2009b0d146b68cc93603ab903ea7a9be Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 10 Jul 2019 17:34:38 -0400 Subject: [PATCH 218/337] Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle --- .../blackbox/messages/InboundMessageType.java | 23 ------------------- .../monitoring/blackbox/package-info.java | 16 ------------- settings.gradle | 19 +++------------ 3 files changed, 3 insertions(+), 55 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/package-info.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java deleted file mode 100644 index 0a584dfa2a7..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.messages; - -/** - * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in - * channel pipeline - */ -public interface InboundMessageType { - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java b/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java deleted file mode 100644 index b3d22bfd24d..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/package-info.java +++ /dev/null @@ -1,16 +0,0 @@ -// 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. - -@javax.annotation.ParametersAreNonnullByDefault -package google.registry.monitoring.blackbox; \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 9b2d11de8da..da47097cb53 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,17 +1,3 @@ -// Copyright 2019 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. - if (pluginsUrl) { println "Plugins: Using repo $pluginsUrl..." pluginManagement { @@ -30,9 +16,10 @@ rootProject.name = 'nomulus' include 'core' include 'prober' include 'proxy' -include 'third_party' -include 'util' include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' +include 'third_party' +include 'util' + From 961eee3fee58ba85d3b6d82cde7ebfa02307c697 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 11 Jul 2019 09:25:54 -0400 Subject: [PATCH 219/337] Removed AutoVaue ignore clause from .gitignore --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 199c4fe3979..327b22fe2e7 100644 --- a/.gitignore +++ b/.gitignore @@ -85,9 +85,6 @@ nomulus.iws # Javascript output **/out/* -# AutoValue generated code -AutoValue_.*.java - ###################################################################### # Python Ignores From d3110ec4eae0187434c27e6bc496d6c64b366afb Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 220/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 3 +- .../google/registry/xjc/package-info.java | 3 +- prober/build.gradle | 63 +++---- .../monitoring/blackbox/NewChannelAction.java | 110 ++++++++--- .../registry/monitoring/blackbox/Prober.java | 23 +-- .../monitoring/blackbox/ProbingAction.java | 173 +++++++++++------- .../handlers/ServerSideException.java | 15 ++ .../handlers/SslClientInitializer.java | 20 +- .../handlers/WebWhoisActionHandler.java | 152 +++++---------- .../blackbox/messages/HttpRequestMessage.java | 70 +------ .../messages/HttpResponseMessage.java | 46 +++-- .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 15 files changed, 346 insertions(+), 340 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index ddff37c6807..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,3 +14,4 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.ui; + diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 5b5456585cc..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,3 +14,4 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.xjc; + diff --git a/prober/build.gradle b/prober/build.gradle index 33feefb7175..a277fb4f9f3 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -1,25 +1,26 @@ -apply plugin: 'java' - -createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Main') +// Copyright 2019 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. +createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') dependencies { - def deps = rootProject.dependencyMap + def deps = rootProject.dependencyMap - compile deps['com.beust:jcommander'] - compile deps['com.google.api-client:google-api-client'] - compile deps['com.google.apis:google-api-services-cloudkms'] - compile deps['com.google.apis:google-api-services-monitoring'] - compile deps['com.google.apis:google-api-services-storage'] compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] - compile deps['com.google.http-client:google-http-client'] - compile deps['com.google.monitoring-client:metrics'] - compile deps['com.google.monitoring-client:stackdriver'] compile deps['io.netty:netty-buffer'] compile deps['io.netty:netty-codec-http'] compile deps['io.netty:netty-codec'] @@ -28,26 +29,20 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - compile project(':util') - runtime deps['com.google.flogger:flogger-system-backend'] - runtime deps['com.google.auto.value:auto-value'] - runtime deps['io.netty:netty-tcnative-boringssl-static'] + runtime deps['com.google.flogger:flogger-system-backend'] + runtime deps['com.google.auto.value:auto-value'] + runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.monitoring-client:contrib'] - testCompile deps['com.google.truth:truth'] - testCompile deps['org.yaml:snakeyaml'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') - testCompile project(path: ':core', configuration: 'testRuntime') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') - // Include auto-value in compile until nebula-lint understands - // annotationProcessor - annotationProcessor deps['com.google.auto.value:auto-value'] - testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] -} \ No newline at end of file + // Include auto-value in compile until nebula-lint understands + // annotationProcessor + annotationProcessor deps['com.google.auto.value:auto-value'] + testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index ce452e19bf0..0ba3a0c22be 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -1,70 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOutboundInvoker; import io.netty.channel.ChannelPromise; -import io.netty.channel.DefaultChannelPromise; -import io.netty.channel.socket.nio.NioSocketChannel; -import org.joda.time.Duration; - +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ @AutoValue -public abstract class NewChannelAction extends ProbingAction { - abstract Bootstrap bootstrap(); +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ private Channel channel; + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ @Override public Channel channel() { return this.channel; } + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ @Override public ChannelFuture call() { + + //Calls on bootstrap method Bootstrap bootstrap = bootstrap(); bootstrap.handler( - new ChannelInitializer() { + new ChannelInitializer() { @Override - protected void initChannel(NioSocketChannel outboundChannel) + protected void initChannel(C outboundChannel) throws Exception { - addHandlers( - outboundChannel.pipeline(), protocol().handlerProviders()); + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); } - }); + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; - ChannelFuture connectionFuture = bootstrap.connect(protocol().host(), protocol().port()); - ChannelPromise finished = null; + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - this.channel = channelFuture.channel(); + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); } else { - + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); } } ); return finished; } - public static ProbingAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder(); + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder outboundMessage(O value); + public abstract NewChannelAction.Builder address(LocalAddress value); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 433d7361d5b..333330207f1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,30 +14,17 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by - * Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** - * Main Dagger Component - */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() - .build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2ccf818a57a..2441debb12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,10 +14,13 @@ package google.registry.monitoring.blackbox; +import static com.google.common.flogger.StackSize.SMALL; -import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.bootstrap.Bootstrap; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.util.AttributeKey; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -31,82 +34,144 @@ import javax.inject.Provider; /** - *Class that represents given action in sequence of probing + *Superclass that represents action generated by {@link ProbingStep} * + *

Inherits from {@link Callable}, as it has can be called + * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the + * task has been completed

+ * + *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. + * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} + * gives the outline and {@link ProbingAction} gives the details of that connection.

+ * + *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

*/ -public abstract class ProbingAction implements Callable { +public abstract class ProbingAction implements Callable { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + /** - * timer that rate limits probing - */ + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; + + + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; + } + + /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** - * @return actual Duration of delay - */ - abstract Duration delay(); - /** - * @return message to send to server - */ - abstract O outboundMessage(); + /** Actual {@link Duration} of this delay */ + public abstract Duration delay(); - /** - * @return Channel object that represents connection between prober client and server - */ - abstract Channel channel(); + /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ + public abstract OutboundMessageType outboundMessage(); - /** - * @return The Protocol instance that represents action to be tested by this part in sequences - */ - abstract Protocol protocol(); + /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + public abstract Channel channel(); - /** - * @return The requisite instance of Action Handler, which is always the last Handler in the pipeline - */ - abstract Bootstrap bootstrap(); - abstract ActionHandler actionHandler(); + /** The {@link Protocol} instance that specifies type of connection */ + public abstract Protocol protocol(); + + public abstract String host(); + + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); - /** - * - * @return Builder for the ProbingAction Class - */ + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> finished.setSuccess(), + future -> { + if (!protocol().persistentConnection()) { + + //If we created a new channel for this action, close the connection to the channel + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } /** - * The method that calls the ActionHandler to send a message down the channel pipeline + * The method that sends the {@code outboundMessage} down the channel pipeline + * * @return future that denotes when the action has been successfully performed */ + @Override public ChannelFuture call() { - // Add the Handlers from the run the action - // (with delay if present), and remove the ActionHandler afterwards, - // in case the channel is to be reused later. + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + } + + //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); - timer.newTimeout(timeout -> - // Retry logic may also be added here. - actionHandler().apply(outboundMessage()).addListeners( - future -> finished.setSuccess()), - delay().getStandardSeconds(), - TimeUnit.SECONDS); + + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } + return finished; } - abstract static class Builder, P extends ProbingAction> { + public abstract static class Builder, P extends ProbingAction> { public abstract B delay(Duration value); - public abstract B outboundMessage(O value); + public abstract B outboundMessage(OutboundMessageType value); public abstract B protocol(Protocol value); - public abstract B actionHandler(ActionHandler value); + public abstract B host(String value); + + public abstract B path(String value); public abstract P build(); + } + /** + * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified + * * @param channelPipeline is pipeline associated with channel that we want to add handlers to * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified @@ -118,22 +183,4 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } - - - - /** - * @param channelPipeline is pipeline associated with channel we want to remove handlers from - * removes all handlers from pipeline - */ - static void removeHandlers(ChannelPipeline channelPipeline) { - while (channelPipeline.first() != null) { - channelPipeline.removeFirst(); - } - } - - - - } - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index c62668b19b2..ac844ac99df 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,11 +15,12 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; + +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler.Sharable; @@ -63,8 +64,7 @@ public SslClientInitializer(SslProvider sslProvider) { this(sslProvider, null, null, null); } - public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, - Supplier certificateSupplier) { + public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, Supplier certificateSupplier) { //We use the default trust store here as well, setting trustCertificates to null this(sslProvider, null, privateKeySupplier, certificateSupplier); } @@ -89,8 +89,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - String host = channel.attr(REMOTE_ADDRESS_KEY).get(); + ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); + Protocol protocol = action.protocol(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -98,14 +98,12 @@ protected void initChannel(C channel) throws Exception { SslContextBuilder.forClient() .sslProvider(sslProvider) .trustManager(trustedCertificates); - if (privateKeySupplier != null && certificateSupplier != null) { - sslContextBuilder = sslContextBuilder - .keyManager(privateKeySupplier.get(), certificateSupplier.get()); - } + if (privateKeySupplier != null && certificateSupplier != null) + sslContextBuilder = sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get()); SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), host, protocol.port()); + .newHandler(channel.alloc(), action.host(), protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index c56c8c7d97c..21010f0e887 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,21 +14,24 @@ package google.registry.monitoring.blackbox.handlers; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; + import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -36,74 +39,39 @@ import org.joda.time.Duration; /** - * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response - * implies a redirection it follows the redirection until either an Error Response is received, or - * {@link HttpResponseStatus.OK} is received

+ *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection + * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

*/ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** - * {@link Bootstrap} necessary for remaking connection on redirect response. - */ - private final Bootstrap bootstrap; - - /** - * {@link Protocol} for when redirected to http endpoint. - */ - private final Protocol httpWhoisProtocol; - - /** - * {@link Protocol} for when redirected to https endpoint. - */ - private final Protocol httpsWhoisProtocol; - - /** - * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. - */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } + public WebWhoisActionHandler() {} /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, - * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a - * response indicating a Failure, or receives a redirection response, where it follows the - * redirects until receiving one of the previous three responses. + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { + throws ServerSideException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status().equals(HttpResponseStatus.OK)) { + + if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - //On success, we always pass message to ActionHandler's channelRead0 method. - super.channelRead0(ctx, msg); + finished.setSuccess(); + + logger.atInfo().log("Response Received: " + response); - } else if (response.status().equals(HttpResponseStatus.MOVED_PERMANENTLY) - || response.status().equals(HttpResponseStatus.FOUND)) { - //TODO - Fix checker to better determine when we have encountered a redirection response. + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { //Obtain url to be redirected to URL url; @@ -111,75 +79,55 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException( - "Redirected Location was invalid. Given Location was: " + response.headers() - .get("Location")); + throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); + int newPort = url.getDefaultPort(); - logger.atInfo().log(String - .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, - url.getDefaultPort(), newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException( - "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); - } + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); + + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) .build(); + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } - - //Once channel is closed, establish new connection to redirected host, and repeat - // same actions + logger.atInfo().log("Successfully Closed Connection"); + + //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell - // ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE + finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b850cfb3b26..3fb8c187ad9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -19,40 +5,20 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import java.util.Arrays; -import javax.inject.Inject; -/** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. - * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a {@code - * name} method, which returns a standard name and the current hostname.

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, - ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } - /** - * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} - */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } @Override public HttpRequestMessage setUri(String path) { @@ -60,31 +26,15 @@ public HttpRequestMessage setUri(String path) { return this; } - /** - * Modifies headers to reflect new host and new path if applicable. - */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) { - setUri(args[1]); - } - - return this; + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + ByteBuf buf = request.content(); + if (buf == null) { + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - throw new IllegalArgumentException( - String.format( - "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of 2. Received arguments: " - + Arrays.toString(args), args.length)); + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - } - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 7d2ff722076..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,21 +6,33 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} - */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { + super(version, status); + } + + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } - /** - * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} - */ - public HttpResponseMessage(FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); + + return finalResponse; } + + + } diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From a73ba4fc0e888f8801f43c258f5bd80c35c82cca Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 221/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 20 +- .../blackbox/ExistingChannelAction.java | 48 +++ .../monitoring/blackbox/NewChannelAction.java | 9 +- .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProberModule.java | 101 +++--- .../monitoring/blackbox/ProbingAction.java | 17 +- .../monitoring/blackbox/ProbingSequence.java | 110 ++++++- .../monitoring/blackbox/ProbingStep.java | 177 ++++++++-- .../monitoring/blackbox/ProbingStepWeb.java | 45 +++ .../monitoring/blackbox/Protocol.java | 64 ++-- .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 +++ .../blackbox/Tokens/WebWhoisToken.java | 57 ++++ .../monitoring/blackbox/WebWhoisModule.java | 242 ++++++-------- .../exceptions/EppClientException.java | 29 ++ .../blackbox/exceptions/FailureException.java | 15 +- .../exceptions/InternalException.java | 29 ++ .../exceptions/ResponseException.java | 29 ++ .../exceptions/ServerSideException.java | 29 ++ .../blackbox/handlers/ActionHandler.java | 91 +++++- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/ServerSideException.java | 15 - .../handlers/WebWhoisActionHandler.java | 17 +- .../handlers/WebWhoisMessageHandler.java | 42 +-- .../blackbox/messages/HttpRequestMessage.java | 9 +- .../messages/OutboundMessageType.java | 17 +- .../blackbox/ProbingActionTest.java | 181 ++++++----- .../blackbox/ProbingSequenceStepTest.java | 219 +++++++++++++ .../blackbox/TestServers/TestServer.java | 85 +++++ .../blackbox/TestServers/WebWhoisServer.java | 92 ++++++ .../monitoring/blackbox/TestUtils.java | 198 +++++++++++- .../monitoring/blackbox/TokenTest.java | 60 ++++ .../blackbox/handlers/ConversionHandler.java | 23 +- .../blackbox/handlers/NettyRule.java | 125 +++----- .../handlers/SslClientInitializerTest.java | 79 +++-- .../blackbox/handlers/TestActionHandler.java | 19 +- .../handlers/WebWhoisActionHandlerTest.java | 303 ++++++++++++------ 37 files changed, 1975 insertions(+), 732 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/build.gradle b/prober/build.gradle index a277fb4f9f3..993da44655d 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -4,7 +4,7 @@ // 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 +// 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, @@ -12,12 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +apply plugin: 'java' + createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] @@ -29,15 +34,18 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - testCompile deps['com.google.truth:truth'] - testCompile deps['junit:junit'] - testCompile deps['org.mockito:mockito-core'] - testCompile project(':third_party') + testCompile deps['com.google.truth:truth'] + testCompile deps['junit:junit'] + testCompile deps['org.mockito:mockito-core'] + testCompile project(':third_party') + //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -46,3 +54,5 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -15,6 +15,8 @@ package google.registry.monitoring.blackbox; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -36,9 +38,6 @@ public abstract class NewChannelAction extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -86,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -119,7 +118,7 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 333330207f1..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,16 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index e5a71636173..73bd9127852 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,84 +14,99 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import io.netty.channel.Channel; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SslProvider; import java.util.Set; import javax.inject.Singleton; -import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and - * stores {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link - * ProbingSequence}. + * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} + * + *

Provides

*/ @Module public class ProberModule { + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; - /** - * Default {@link Duration} chosen to be time between each {@link ProbingAction} call. - */ - private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - - /** - * {@link Provides} the {@link SslProvider} used by instances of {@link - * google.registry.monitoring.blackbox.handlers.SslClientInitializer} - */ @Provides @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + EventLoopGroup provideEventLoopGroup() { + return new NioEventLoopGroup(); } - /** - * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. - */ @Provides - @Singleton - EventLoopGroup provideEventLoopGroup() { - return new NioEventLoopGroup(); + @HttpWhoisProtocol + ProbingSequence provideHttpWhoisSequence( + @HttpWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** - * {@link Provides} one global {@link Channel} class that is used to construct a {@link - * io.netty.bootstrap.Bootstrap}. - */ @Provides - @Singleton - Class provideChannelClazz() { - return NioSocketChannel.class; + @HttpsWhoisProtocol + ProbingSequence provideHttpsWhoisSequence( + @HttpsWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** - * {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. - */ @Provides - @Singleton - Duration provideDuration() { - return DEFAULT_DURATION; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } - /** - * Root level {@link Component} that provides each {@link ProbingSequence}. - */ + @Provides + @HttpsWhoisProtocol + int provideHttpsWhoisPort() { + return httpsWhoIsPort; + } + + @Provides + ImmutableMap providePortToProtocolMap( + Set protocolSet) { + return Maps.uniqueIndex(protocolSet, Protocol::port); + } + + + @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, + TokenModule.class }) public interface ProberComponent { - //Standard WebWhois sequence - Set sequences(); + @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); + + @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); + + ImmutableMap providePortToProtocolMap(); + + @WebWhoisProtocol Token provideWebWhoisToken(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2441debb12d..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -34,7 +34,7 @@ import javax.inject.Provider; /** - *Superclass that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -183,4 +183,19 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + @Override + public String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n" + + "path: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host(), + path() + ); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 7c14d9f0bf0..6387207fea4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -1,42 +1,122 @@ +// Copyright 2019 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.monitoring.blackbox; -class ProbingSequence { - private ProbingStep firstStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.EventLoopGroup; + +/** + * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * + * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} + * but for tests is {@link LocalChannel} + * + *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, + * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * + *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one + * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ */ +public class ProbingSequence { + private ProbingStep firstStep; + + /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ + private EventLoopGroup eventGroup; + + /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ + private Bootstrap bootstrap; + + public Bootstrap getBootstrap() { + return bootstrap; + } - public void start() { - // create a new unique token; - Token token = new TestToken<>(); + public void start(Token token) { + // calls the first step with input token; firstStep.accept(token); } /** - * Builder that sequentially adds steps + * {@link Builder} which takes in {@link ProbingStep}s + * + * @param Same specified {@code C} for overall {@link ProbingSequence} */ - static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; + public static class Builder { + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstSequenceStep; + private EventLoopGroup eventLoopGroup; + private Class classType; - public Builder addStep(ProbingStep step) { + Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; + return this; + } + + Builder addStep(ProbingStep step) { if (currentStep == null) { firstStep = step; } else { currentStep.nextStep(step); } - currentStep = step; return this; + } + /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ + Builder makeFirstRepeated() { + firstSequenceStep = currentStep; + return this; + } + /** Set the class to be the same as {@code C} */ + public Builder setClass(Class classType) { + this.classType = classType; + return this; } - public ProbingSequence build() { - currentStep.nextStep(firstStep); - return new ProbingSequence(this.firstStep); + public ProbingSequence build() { + currentStep.nextStep(firstSequenceStep); + currentStep.lastStep(); + return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); } } - private ProbingSequence(ProbingStep firstStep) { + /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ + private void setParents() { + ProbingStep currentStep = firstStep.parent(this).nextStep(); + + while (currentStep != firstStep) { + currentStep = currentStep.parent(this).nextStep(); + } + } + private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, + Class classType) { this.firstStep = firstStep; + this.eventGroup = eventLoopGroup; + this.bootstrap = new Bootstrap() + .group(eventGroup) + .channel(classType); + setParents(); + } + + @Override + public String toString() { + return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 2e2e3575d07..5bad5abf6bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -1,61 +1,170 @@ +// Copyright 2019 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.monitoring.blackbox; -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.io.IOException; import java.util.function.Consumer; +import org.joda.time.Duration; + +/** + * Represents generator of actions performed at each step in {@link ProbingSequence} + * + * @param See {@code C} in {@link ProbingSequence} + * + *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are + * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies + * these components on each loop iteration with the consumed {@link Token} and from that, + * generates new {@link ProbingAction} to perform<./p> + * + *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

+ */ +public abstract class ProbingStep implements Consumer { + + public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); + protected static final Duration DEFAULT_DURATION = new Duration(2000L); + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + protected LocalAddress address = DEFAULT_ADDRESS; + + /** Necessary boolean to inform when to obtain next {@link Token}*/ + private boolean isLastStep = false; + private ProbingStep nextStep; + private ProbingSequence parent; + + protected Duration duration; + + protected final Protocol protocol; + protected final OutboundMessageType message; + + protected ProbingStep(Protocol protocol, OutboundMessageType message) { + this.protocol = protocol; + this.message = message; + } + + private OutboundMessageType message() { + return message; + } + Protocol protocol() { + return protocol; + } -public class ProbingStep implements Consumer> { - private ProbingStep nextStep; + void lastStep() { + isLastStep = true; + } - public void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - public ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } + ProbingStep parent(ProbingSequence parent) { + this.parent = parent; + return this; + } + /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + private ProbingAction generateAction(Token token) throws InternalException { + ProbingAction generatedAction; + + OutboundMessageType message = token.modifyMessage(message()); + + //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction + if (protocol().persistentConnection() && token.channel() != null) { + generatedAction = ExistingChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .channel(token.channel()) + .build(); + } else { + generatedAction = NewChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .bootstrap(parent.getBootstrap()) + .address(address) + .build(); + + } + return generatedAction; + } - private ProbingAction generateAction(Token token) { - // Construct a new ProbingAction and return it. - // The action is only used for one invocation - // and uses the UniqueToken provided in the argument, to - // populate fields in the action. The UniqueToken contains - // all the information needed to create an action, including - // for example the test domain name to be created/deleted and - // the channel to reuse (for ExistingChannelActions). - - return NewChannelAction.builder() - .protocol(token.protocol()) - .outboundMessage(token.message()) - .actionHandler(token.actionHandler()) - .delay(token.DEFAULT_DURATION) - .build(); + /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + private Token generateNextToken(Token token) { + return (isLastStep) ? token.next() : token; } - private Token generateNextToken(Token token) { - // Given the input token, we should be able to deduce what - // this the token for the following steps to use. If this - // step generates an action to create a domain, and the next - // one checks for its existence, the domain contained in the - // token should not change. If this is the last step in a loop - // on the other hand, the next token should contain a new - // domain name for the next loop. - return token.next(); + @Override + public void accept(Token token) { + ProbingAction nextAction; + //attempt to generate new action. On error, move on to next step + try { + nextAction = generateAction(token); + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Generation"); + nextStep.accept(generateNextToken(token)); + return; + } + + //If the next step maintains the connection, pass on the channel from this + if (protocol().persistentConnection()) { + token.channel(nextAction.channel()); + } + + //call the created action + ChannelFuture future = nextAction.call(); + + //On result, either log success and move on, or + future.addListener(f -> { + if (f.isSuccess()) { + logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); + nextStep.accept(generateNextToken(token)); + } else { + logger.atSevere().withCause(f.cause()).log("Did not result in future success"); + } + }); } @Override - public void accept(Token token) { - ChannelFuture future = generateAction(token).call(); - future.addListener(f -> nextStep().accept(generateNextToken(token))); + public String toString() { + return String.format("ProbingStep with Protocol: %s\n" + + "OutboundMessage: %s\n" + + "and parent sequence: %s", + protocol(), + message(), + parent); } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 3ddecba5af7..5e08173948e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -16,60 +16,56 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; import javax.inject.Provider; +/** + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection + */ @AutoValue public abstract class Protocol { - /** - * Default names associated with each protocol - */ - final static String EPP_PROTOCOL_NAME = "EPP"; - final static String DNS_PROTOCOL_NAME = "DNS"; - final static String WHOIS_PROTOCOL_NAME = "WHOIS"; - final static String RDAP_PROTOCOL_NAME = "RDAP"; - - final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - public boolean PERSISTENT_CONNECTION = name() == EPP_PROTOCOL_NAME; - /** - * @return name of Protocol. - */ abstract String name(); - /** - * @return Port to bind to at remote host - */ - abstract int port(); - - /** - * @return hostname to connect to - */ - abstract String host(); + public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ abstract ImmutableList> handlerProviders(); - /** Builds new Protocol from @AutoValue Builder implementation*/ - static Protocol.Builder builder() { + /** Boolean that notes if connection associated with Protocol is persistent.*/ + abstract boolean persistentConnection(); + + public abstract Builder toBuilder(); + + public static Builder builder() { return new AutoValue_Protocol.Builder(); } - + /** Builder for {@link Protocol}. */ @AutoValue.Builder - public static abstract class Builder { + public abstract static class Builder { - abstract Builder name(String value); + public abstract Builder name(String value); - abstract Builder host(String value); + public abstract Builder port(int num); - abstract Builder port(int num); + public abstract Builder handlerProviders( + ImmutableList> providers); - abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder persistentConnection(boolean value); - abstract Protocol build(); + public abstract Protocol build(); } - + @Override + public String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 8365607da40..dba905c0e49 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,61 +18,61 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; + +import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.time.Duration; -/** - * A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. - */ +/** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - private static final String HTTP_PROTOCOL_NAME = "http"; - private static final String HTTPS_PROTOCOL_NAME = "https"; - /** - * Standard length of messages used by Proxy. Equates to 0.5 MB. - */ - private static final int maximumMessageLengthBytes = 512 * 1024; - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; - - /** - * {@link Provides} only step used in WebWhois sequence. - */ + final static String DOMAIN_SUFFIX = "whois.nic."; + + + /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ + @Qualifier + @interface HttpWhoisProtocol {} + + /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ + @Qualifier + @interface HttpsWhoisProtocol {} + + /** Dagger qualifier to provide any WebWhois related bindings. */ + @Qualifier + public @interface WebWhoisProtocol {} + + + + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + + @Provides - @WebWhoisProtocol - static ProbingStep provideWebWhoisStep( - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @WebWhoisProtocol Bootstrap bootstrap, - HttpRequestMessage messageTemplate, - Duration duration) { - - return ProbingStep.builder() - .setProtocol(httpWhoisProtocol) - .setBootstrap(bootstrap) - .setMessageTemplate(messageTemplate) - .setDuration(duration) - .build(); + @HttpWhoisProtocol + static ProbingStep provideHttpWhoisProbingSequence( + @HttpWhoisProtocol Protocol httpWhoisProtocol) { + return new ProbingStepWeb<>(httpWhoisProtocol); + } + + @Provides + @HttpsWhoisProtocol + static ProbingStep provideHttpsWhoisProbingStep( + @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { + return new ProbingStepWeb<>(httpsWhoisProtocol); } - /** - * {@link Provides} the {@link Protocol} that corresponds to http connection. - */ + @Singleton @Provides @HttpWhoisProtocol @@ -80,16 +80,28 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTP_PROTOCOL_NAME) - .setPort(httpWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** - * {@link Provides} the {@link Protocol} that corresponds to https connection. - */ + @Singleton + @Provides + @IntoSet + static Protocol provideHttpProtocolForSet( + @HttpWhoisProtocol int httpWhoisPort, + @HttpWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Singleton @Provides @HttpsWhoisProtocol @@ -97,23 +109,40 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTPS_PROTOCOL_NAME) - .setPort(httpsWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** - * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http - * protocol. - */ + @Singleton + @Provides + @IntoSet + static Protocol provideHttpsProtocolForSet( + @HttpsWhoisProtocol int httpsWhoisPort, + @HttpsWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Provides + @WebWhoisProtocol + String provideHttpWhoisHost() { + return "app"; + } + + @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -122,18 +151,13 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** - * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https - * protocol. - */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( - @HttpsWhoisProtocol - Provider> sslClientInitializerProvider, + @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -143,106 +167,34 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } - @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); - } - - @Provides - static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { - return new HttpObjectAggregator(maxContentLength); - } - - /** - * {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. - */ - @Provides - @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer( - SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); - } - /** - * {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. - */ - @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap( - EventLoopGroup eventLoopGroup, - Class channelClazz) { - return new Bootstrap() - .group(eventLoopGroup) - .channel(channelClazz); + static MessageHandler provideMessageHandler() { + return new WebWhoisMessageHandler(); } - /** - * {@link Provides} standard WebWhois sequence. - */ @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { - - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); - } - - @Provides - @WebWhoisProtocol - int provideMaximumMessageLengthBytes() { - return maximumMessageLengthBytes; + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); } - /** - * {@link Provides} the list of top level domains to be probed - */ - @Singleton @Provides - @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy", "xn--q9jyb4c"); + static HttpObjectAggregator provideHttpObjectAggregator() { + return new HttpObjectAggregator(1048576); } @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return HTTP_WHOIS_PORT; + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } @Provides @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return HTTPS_WHOIS_PORT; - } - - /** - * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. - */ - @Qualifier - public @interface HttpWhoisProtocol { - - } - - /** - * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. - */ - @Qualifier - public @interface HttpsWhoisProtocol { - - } - - /** - * Dagger qualifier to provide any WebWhois related bindings. - */ - @Qualifier - public @interface WebWhoisProtocol { - + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 36687e7ac82..016c3eb32c7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,18 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.exceptions; +package google.registry.monitoring.blackbox.messages; /** - * Base exception class for all instances when the status of the action performed is FAILURE. + * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in + * channel pipeline */ -public class FailureException extends Exception { +public interface InboundMessageType {} - public FailureException(String msg) { - super(msg); - } - - public FailureException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java new file mode 100644 index 00000000000..31196d776f4 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 21797cce800..c3622e1b810 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,39 +14,96 @@ package google.registry.monitoring.blackbox.handlers; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import java.util.function.Function; +import io.netty.channel.SimpleChannelInboundHandler; -public class ActionHandler extends SimpleChannelInboundHandler - implements Function { +/** + * Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + * + *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, + * as it should only be passed in messages that implement the {@link InboundMessageType} interface. + * + *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link + * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. + * Second, it stores the {@link OutboundMessageType} passed down the pipeline, so that subclasses + * can use that information for their own processes. Lastly, with any exception thrown, the + * connection is closed, and the ProbingAction governing this channel is informed of the error. + * Subclasses specify further work to be done for specific kinds of channel pipelines. + */ +public abstract class ActionHandler extends SimpleChannelInboundHandler { - private ChannelPromise finished; - private Channel channel; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - @Override - public ChannelFuture apply(O outboundMessage) { - // Send the request to server. - channel.writeAndFlush(outboundMessage); + /** Three types of responses received down pipeline */ + public enum ResponseType {SUCCESS, FAILURE, ERROR} + + /** Status of response for current {@link ActionHandler} instance */ + private static ResponseType status; + + protected ChannelPromise finished; + + /** + * Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized + * {@link ChannelPromise} + */ + public ChannelFuture getFuture() { return finished; } + /** Initializes new {@link ChannelPromise} */ @Override public void handlerAdded(ChannelHandlerContext ctx) { - channel = ctx.channel(); + // Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } @Override - protected void channelRead0(ChannelHandlerContext ctx, I InboundMessage) { - // Response received, validate it, register metrics, etc. - // Once everything is done, mark the promise as success; - + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + //simply marks finished as success + status = ResponseType.SUCCESS; finished.setSuccess(); } + /** + * Logs the channel and pipeline that caused error, closes channel, then informs {@link + * ProbingAction} listeners of error + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + logger.atSevere().withCause(cause).log( + String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), ctx.channel().pipeline().toString())); + + + if (ResponseException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + status = ResponseType.FAILURE; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (ServerSideException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + status = ResponseType.ERROR; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (InternalException.class.isInstance(cause)){ + logger.atSevere().withCause(cause).log("Severe internal error"); + finished.setFailure(cause); + } else { + finished.setFailure(cause); + } + + //due to failure, close channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java deleted file mode 100644 index 5d3addb920e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ /dev/null @@ -1,15 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 21010f0e887..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -17,20 +17,16 @@ import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; @@ -59,7 +55,7 @@ public WebWhoisActionHandler() {} */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ServerSideException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -67,9 +63,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - finished.setSuccess(); - logger.atInfo().log("Response Received: " + response); + super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -79,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -126,8 +121,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + throw new ResponseException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 576d6a04d42..4afc5d95ba7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,59 +1,33 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -/** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom - * type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for - * redirection. - */ -public class WebWhoisMessageHandler extends ChannelDuplexHandler { +public class WebWhoisMessageHandler extends MessageHandler { + + private HttpRequestMessage request; @Inject - public WebWhoisMessageHandler() { - } + public WebWhoisMessageHandler() {} - /** - * Retains {@link HttpRequestMessage} and calls super write method. - */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) - throws Exception { - HttpRequestMessage request = (HttpRequestMessage) msg; + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** - * Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link - * InboundMessageType} instance. - */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + FullHttpResponse originalResponse = (FullHttpResponse) msg; - HttpResponseMessage response = new HttpResponseMessage(originalResponse); + InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 3fb8c187ad9..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -28,13 +28,14 @@ public HttpRequestMessage setUri(String path) { public static HttpRequestMessage fromRequest(FullHttpRequest request) { ByteBuf buf = request.content(); - + HttpRequestMessage output; if (buf == null) { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 4a7c16243cd..ba50d0707ec 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,24 +14,9 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; - /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in * channel pipeline */ -public interface OutboundMessageType { - - /** - * All {@link OutboundMessageType} implementing classes should be able to be modified by token - * with String arguments - */ - OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; +public interface OutboundMessageType {} - /** - * Necessary to inform metrics collector what kind of message is sent down {@link - * io.netty.channel.ChannelPipeline} - */ - @Override - String toString(); -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index df3296438af..cbcf2fc82b0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,102 +15,135 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import javax.inject.Provider; import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; - /** * Unit tests for {@link ProbingAction} subtypes * *

Attempts to test how well each {@link ProbingAction} works with an {@link ActionHandler} * subtype when receiving to all possible types of responses

- */ + * */ @RunWith(JUnit4.class) public class ProbingActionTest { + /** Necessary Constants for test */ + private final String TEST_MESSAGE = "MESSAGE_TEST"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final int TEST_PORT = 0; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - private static final String TEST_MESSAGE = "MESSAGE_TEST"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final int TEST_PORT = 0; + private ProbingAction newChannelAction; + private ProbingAction existingChannelAction; + private EmbeddedChannel channel; + private Protocol protocol; - private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - /** - * Used for testing how well probing step can create connection to blackbox server - */ + /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** - * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on - * {@link ProbingAction} - */ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - //TODO - Currently, this test fails to receive outbound messages from the embedded channel, which - // we will fix in a later release. - @Ignore - @Test - public void testSuccess_existingChannel() { - //setup - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up a Protocol corresponding to when a connection exists. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(true) + /** Sets up a {@link Protocol} corresponding to when a new connection is created */ + private void setupNewChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(false) + .build(); + } + /** Sets up a {@link Protocol} corresponding to when a new connection exists */ + private void setupExistingChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(true) .build(); + } - // Sets up a ProbingAction that creates a channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setChannel(channel) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost("") + /** Sets up a {@link NewChannelAction} with test specified attributes */ + private void setupNewChannelAction() { + newChannelAction = NewChannelAction.builder() + .bootstrap(bootstrap) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .address(address) .build(); + } - //tests main function of ProbingAction - ChannelFuture future = action.call(); + private void setupChannel() { + channel = new EmbeddedChannel(); + } - //Obtains the outboundMessage passed through pipeline after delay - Object msg = null; - while (msg == null) { - msg = channel.readOutbound(); - } - //tests the passed message is exactly what we expect - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - assertThat(request).isEqualTo(TEST_MESSAGE); + /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + private void setupExistingChannelAction(Channel channel) { + existingChannelAction = ExistingChannelAction.builder() + .channel(channel) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .build(); + } + + @Test + public void testBehavior_existingChannel() { + //setup + setupChannel(); + setupExistingChannelProtocol(); + setupExistingChannelAction(channel); + channel.pipeline().addLast(conversionHandler); + channel.pipeline().addLast(testHandler); + + + ChannelFuture future = existingChannelAction.call(); - // Ensures that we haven't marked future as done until response is received. - assertThat(future.isDone()).isFalse(); + //Ensures that we pass in the right message to the channel and haven't marked the future as success yet + Object msg = channel.readOutbound(); + assertThat(msg).isInstanceOf(ByteBuf.class); + String response = ((ByteBuf) msg).toString(UTF_8); + assertThat(response).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()).isFalse(); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); @@ -122,41 +155,19 @@ public void testSuccess_existingChannel() { @Test public void testSuccess_newChannel() throws Exception { //setup + setupNewChannelProtocol(); + setupNewChannelAction(); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - LocalAddress address = new LocalAddress(ADDRESS_NAME); - Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); - - // Sets up a Protocol corresponding to when a new connection is created. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - - nettyRule.setUpServer(address); - - // Sets up a ProbingAction with existing channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future = future.syncUninterruptibly(); + future.sync(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler) testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()); + assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java new file mode 100644 index 00000000000..7a713017072 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java @@ -0,0 +1,219 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.TestUtils.TestStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.handlers.ConversionHandler; +import google.registry.monitoring.blackbox.handlers.NettyRule; +import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.junit.Rule; +import org.junit.Test; + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + + /** Used for testing how well probing step can create connection to blackbox server */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + + + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ + private ProbingSequence testSequence; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); + dummyStep = new DummyStep(testProtocol, eventLoopGroup); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(false) + .build(); + } + + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(true) + .build(); + } + + /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ + private void setupSequence() { + testSequence = new ProbingSequence.Builder() + .eventLoopGroup(eventLoopGroup) + .setClass(LocalChannel.class) + .addStep(firstStep) + .makeFirstRepeated() + .addStep(dummyStep) + .build(); + } + + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //there should be no next step + assertThat(firstStep.nextStep()).isNull(); + + //we expect that this exception be thrown + assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); + + } + + @Test + public void testWithSequence_NewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupSequence(); + setupNewChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupSequence(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java new file mode 100644 index 00000000000..67e2cb7165d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -0,0 +1,85 @@ +package google.registry.monitoring.blackbox.TestServers; + +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; + +/** + * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + */ +public abstract class TestServer { + private LocalAddress localAddress; + + TestServer(LocalAddress localAddress, ImmutableList handlers) { + this(new NioEventLoopGroup(1), localAddress, handlers); + } + + TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + this.localAddress = localAddress; + + //Creates ChannelInitializer with handlers specified + ChannelInitializer serverInitializer = new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) { + for (ChannelHandler handler : handlers) { + ch.pipeline().addLast(handler); + } + } + }; + //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using LocalServerChannel class + ServerBootstrap serverBootstrap = + new ServerBootstrap() + .group(eventLoopGroup) + .channel(LocalServerChannel.class) + .childHandler(serverInitializer); + + ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); + + } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** Saves any inbound error as the cause of the promise failure. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java new file mode 100644 index 00000000000..ab9997b6c68 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -0,0 +1,92 @@ +package google.registry.monitoring.blackbox.TestServers; + +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpServerCodec; + +/** + * {@link TestServer} subtype that performs WebWhois Services Expected + * + * It will either redirect the client to the correct location if given the + * requisite redirect input, give the client a successful response if they give + * the expected final destination, or give the client an error message if given + * an unexpected host location + */ +public class WebWhoisServer extends TestServer { + + public WebWhoisServer(LocalAddress localAddress, ImmutableList handlers) { + super(localAddress, handlers); + } + + public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + super(eventLoopGroup, localAddress, handlers); + } + + /** Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the HttpRequestMessage object through pipeline */ + public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + return new WebWhoisServer( + eventLoopGroup, + localAddress, + ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) + ); + } + /** Creates server that sends exactly what we expect a remote server to send as a response, by sending the {@link ByteBuf} of the response through pipeline */ + public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + return new WebWhoisServer( + eventLoopGroup, + localAddress, + ImmutableList.of( + new HttpServerCodec(), + new HttpObjectAggregator(1048576), + new RedirectHandler(redirectInput, destinationInput)) + ); + } + + /** + * Handler that will wither redirect client, give successful response, or give error messge + */ + @Sharable + static class RedirectHandler extends ChannelDuplexHandler { + private String redirectInput; + private String destinationInput; + + /** + * + * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + */ + public RedirectHandler(String redirectInput, String destinationInput) { + this.redirectInput = redirectInput; + this.destinationInput = destinationInput; + } + + /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + HttpRequest request = (HttpRequest) msg; + HttpResponse response; + if (request.headers().get("host").equals(redirectInput)) { + response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + } else if (request.headers().get("host").equals(destinationInput)) { + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + } else { + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + } + ctx.channel().writeAndFlush(response); + + } + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 66e2928f45e..8d1722c9625 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,23 +14,47 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.joda.time.Duration; -/** - * Utility class for various helper methods used in testing. - */ +/** Utility class for various helper methods used in testing. */ public class TestUtils { + static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -51,20 +75,178 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { return response; } - /** - * Creates HttpResponse given status, redirection location, and other necessary inputs - */ + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ public static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive) { + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain"); + response.headers().set("content-type", "text/plain").set("content-length", "0"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } return response; } + + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); + return response; + } + + /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ + public static class TestProvider implements Provider { + + private E obj; + + public TestProvider(E obj) { + this.obj = obj; + } + + @Override + public E get() { + return obj; + } + } + + /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ + public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { + + String message; + + public DuplexMessageTest() { + message = ""; + } + + public DuplexMessageTest(String msg) { + message = msg; + } + + @Override + public String toString() { + return message; + } + } + + /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ + public static class TestStep extends ProbingStep { + + public TestStep(Protocol protocol, String testMessage, LocalAddress address) { + super(protocol, new DuplexMessageTest(testMessage)); + this.address = address; + this.duration = Duration.ZERO; + } + } + + /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ + public static class DummyStep extends ProbingStep { + private DefaultPromise future; + + public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { + super(protocol, new DuplexMessageTest()); + future = new DefaultPromise(eventLoopGroup.next()) {}; + duration = Duration.ZERO; + } + + @Override + public void accept(Token token) { + future.setSuccess(token); + } + public DefaultPromise getFuture() { + return future; + } + } + + /** Basic outline for {@link Token} instances to be used in tests */ + private static abstract class TestToken extends Token { + private String host; + + protected TestToken(String host) { + this.host = host; + } + @Override + public Token next() { + return this; + } + + @Override + public OutboundMessageType modifyMessage(OutboundMessageType message) { + return message; + } + + @Override + public String getHost() { + return host; + } + + } + + /** {@link TestToken} instance that creates new channel */ + public static class NewChannelToken extends TestToken { + public NewChannelToken(String host) { + super(host); + } + @Override + public Channel channel() { + return null; + } + } + + /** {@link TestToken} instance that passes in existing channel */ + public static class ExistingChannelToken extends TestToken { + private Channel channel; + + public ExistingChannelToken(Channel channel, String host) { + super(host); + this.channel = channel; + } + @Override + public Channel channel() { + return channel; + } + } + + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java new file mode 100644 index 00000000000..ef5cba5b60d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -0,0 +1,60 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + */ +@RunWith(JUnit4.class) +public class TokenTest { + + private static String PREFIX = "whois.nic."; + private static String TEST_STARTER = "starter"; + private static String TEST_DOMAIN = "test"; + + public Token webToken = new WebWhoisToken(TEST_DOMAIN); + + @Test + public void testWebToken_MessageModificationSuccess() { + //creates Request message with header + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + message.headers().set("host", TEST_STARTER); + + //attempts to use Token's method for modifying the method based on its stored host + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { + throw new RuntimeException(e); + } + + + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 987abbfd7dc..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,38 +17,31 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link - * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to + * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** - * Handles inbound conversion - */ + /** Handles inbound conversion */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } - /** - * Handles outbound conversion - */ + /** Handles outbound conversion */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 4b6eed9c16f..b6b5e8fbe0c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -25,11 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingActionTest; -import google.registry.monitoring.blackbox.ProbingStepTest; -import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.testservers.TestServer; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -41,6 +41,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -51,19 +52,12 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest} - *

+ *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

*/ public final class NettyRule extends ExternalResource { - private final EventLoopGroup eventLoopGroup; - // Handler attached to server's channel to record the request received. - private EchoHandler echoHandler; - // Handler attached to client's channel to record the response received. - private DumpHandler dumpHandler; - private Channel channel; // All I/O operations are done inside the single thread within this event loop group, which is // different from the main test thread. Therefore synchronizations are required to make sure that @@ -71,34 +65,31 @@ public final class NettyRule extends ExternalResource { public NettyRule() { eventLoopGroup = new NioEventLoopGroup(1); } - public NettyRule(EventLoopGroup e) { eventLoopGroup = e; } + private final EventLoopGroup eventLoopGroup; + private WebWhoisServer webWhoisServer; - private static void writeToChannelAndFlush(Channel channel, String data) { - ChannelFuture unusedFuture = - channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); - } + // Handler attached to server's channel to record the request received. + private EchoHandler echoHandler; - /** - * Sets up a server channel bound to the given local address. - */ - public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { + // Handler attached to client's channel to record the response received. + private DumpHandler dumpHandler; + + private Channel channel; + + /** Sets up a server channel bound to the given local address. */ + public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - - new TestServer(eventLoopGroup, localAddress, - ImmutableList.builder().add(handlers).add(echoHandler).build()); + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); } - /** - * Sets up a client channel connecting to the give local address. - */ + /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - Protocol protocol, - String host, + ProbingAction probingAction, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -118,9 +109,7 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol) - .attr(REMOTE_ADDRESS_KEY, host); - + .attr(PROBING_ACTION_KEY, probingAction); channel = b.connect(localAddress).syncUninterruptibly().channel(); } @@ -128,10 +117,8 @@ private void checkReady() { checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); } - /** - * Test that custom setup to send message to current server sends right message - */ - public void assertReceivedMessage(String message) throws Exception { + /** Test that custom setup to send message to current server sends right message */ + public void assertThatCustomWorks(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -139,9 +126,9 @@ public void assertReceivedMessage(String message) throws Exception { /** * Test that a message can go through, both inbound and outbound. * - *

The client writes the message to the server, which echos it back and saves the string in - * its promise. The client receives the echo and saves it in its promise. All these activities - * happens in the I/O thread, and this call itself returns immediately. + *

The client writes the message to the server, which echos it back and saves the string in its + * promise. The client receives the echo and saves it in its promise. All these activities happens + * in the I/O thread, and this call itself returns immediately. */ void assertThatMessagesWork() throws Exception { checkReady(); @@ -171,47 +158,9 @@ ThrowableSubject assertThatClientRootCause() { assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); } - @Override - protected void after() { - Future unusedFuture = eventLoopGroup.shutdownGracefully(); - } - - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** - * Saves any inbound error as the cause of the promise failure. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } - /** - * A handler that dumps its inbound message to a promise that can be inspected later. - */ + /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture responseFuture = new CompletableFuture<>(); @@ -232,13 +181,21 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception responseFuture.complete(response); } - /** - * Saves any inbound error into the failure cause of the promise. - */ + /** Saves any inbound error into the failure cause of the promise. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); } } + + @Override + protected void after() { + Future unusedFuture = eventLoopGroup.shutdownGracefully(); + } + + private static void writeToChannelAndFlush(Channel channel, String data) { + ChannelFuture unusedFuture = + channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 2a9f9758e09..469c62a8f75 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,14 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.ExistingChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; @@ -41,6 +45,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; +import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -62,41 +67,42 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - /** - * Fake host to test if the SSL engine gets the correct peer host. - */ + private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); + + /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; - /** - * Fake port to test if the SSL engine gets the correct peer port. - */ + /** Fake port to test if the SSL engine gets the correct peer port. */ private static final int SSL_PORT = 12345; - /** - * Fake protocol saved in channel attribute. - */ - private static final Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + @Rule public NettyRule nettyRule = new NettyRule(); + @Parameter(0) public SslProvider sslProvider; - /** - * Saves the SNI hostname received by the server, if sent by the client. - */ - private String sniHostReceived; // We do our best effort to test all available SSL providers. @Parameters(name = "{0}") public static SslProvider[] data() { return OpenSsl.isAvailable() - ? new SslProvider[]{SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[]{SslProvider.JDK}; + ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[] {SslProvider.JDK}; } + /** Saves the SNI hostname received by the server, if sent by the client. */ + private String sniHostReceived; + + /** Fake protocol saved in channel attribute. */ + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .persistentConnection(false) + .build(); + + private ProbingAction probingAction; + private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { SslContext sslContext = SslContextBuilder.forServer(privateKey, certificate).build(); @@ -107,13 +113,23 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } + private void setupProbingAction(Channel channel) { + probingAction = ExistingChannelAction.builder() + .delay(Duration.ZERO) + .host(SSL_HOST) + .channel(channel) + .outboundMessage(DEFAULT_MESSAGE) + .protocol(PROTOCOL) + .build(); + } + @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - channel.attr(PROTOCOL_KEY).set(PROTOCOL); - channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); + setupProbingAction(channel); + channel.attr(PROBING_ACTION_KEY).set(probingAction); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -144,7 +160,8 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -170,9 +187,10 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -199,9 +217,10 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 19e608c97d2..518bb9ba686 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,27 +14,26 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; /** - * Concrete implementation of {@link ActionHandler} that does nothing different from parent class - * other than store and return the {@code inboundMessage} + * Concrete implementation of {@link ActionHandler} that does nothing different from + * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ - private InboundMessageType receivedMessage; + private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage; + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } - public InboundMessageType getResponse() { + @Override + public String toString() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index a4c2c57dc1a..71d8d66b6c0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,29 +15,35 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import google.registry.monitoring.blackbox.testservers.TestServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; +import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -50,59 +56,50 @@ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; + private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; + private static final String HTTPS_REDIRECT = "https://"; + private static final String REDIRECT_HOST = "www.example.com"; + private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private final Protocol standardProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( - null, null, null, null))) - .setName("http") - .setPersistentConnection(false) - .setPort(HTTP_PORT) - .build(); - + private static final Duration DEFAULT_DURATION = new Duration(0L); + private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; + private ProbingAction probingAction; private Provider actionHandlerProvider; - private Protocol initialProtocol; - private HttpRequestMessage msg; - - /** - * Creates default protocol with empty list of handlers and specified other inputs - */ - private Protocol createProtocol(String name, int port, boolean persistentConnection) { + private void generateLocalAddress() { + address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + } + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() - .setName(name) - .setPort(port) - .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) - .setPersistentConnection(persistentConnection) + .name(name) + .port(port) + .handlerProviders(ImmutableList.of(actionHandlerProvider)) + .persistentConnection(false) .build(); } - /** - * Initializes new WebWhoisActionHandler - */ - private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { - actionHandler = new WebWhoisActionHandler( - bootstrap, - standardProtocol, - standardProtocol, - messageTemplate - ); - actionHandlerProvider = () -> actionHandler; + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); + actionHandlerProvider = new TestProvider<>(actionHandler); } - /** - * Sets up testing channel with requisite attributes - */ - private void setupChannel(Protocol protocol) { + /** Sets up testing channel with requisite attributes */ + private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + setupProbingActionBasic( + protocol, + outboundMessage, + makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -110,123 +107,217 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .group(group) .channel(LocalChannel.class); } + /**Sets up probingAction for when testing redirection */ + private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(TARGET_HOST) + .address(DEFAULT_ADDRESS) + .build(); + } + private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(host) + .address(address) + .build(); + } - private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { - msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); - setupActionHandler(bootstrap, msg); - initialProtocol = createProtocol("testProtocol", 0, persistentConnection); - + private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } @Test - public void testBasic_responseOk() { + public void testBasic_responseOk() throws Exception { //setup - setup("", null, true); - setupChannel(initialProtocol); - + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); - //assesses that we successfully received good response and protocol is unchanged + //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badRequest() { + public void testBasic_responseFailure() { //setup - setup("", null, false); - setupChannel(initialProtocol); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseBad", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); - // Stores future that informs when action is completed. - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + //stores future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage( - makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = HttpResponseMessage + .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); - // Assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); - // Assesses that listener is triggered, but event is not success - assertThat(future.isDone()).isTrue(); + //assesses that listener is triggered, but event is not success + assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isFalse(); - // Ensures that we fail as a result of a FailureException. - assertThat(future.cause() instanceof FailureException).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + } + @Test + public void testBasic_responseError() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseError", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + + //stores future + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, and event is success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testBasic_responseFailure_badURL() { + public void testBasic_redirectCloseChannel() { //setup - setup("", null, false); - setupChannel(initialProtocol); + HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", 0); + generateLocalAddress(); + setupChannel(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true)); + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + + //checks that future has not been set to successful or a failure + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, and event is success - assertThat(future.isDone()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + - // Ensures that we fail as a result of a FailureException. - assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testAdvanced_redirect() { - // Sets up EventLoopGroup with 1 thread to be blocking. - EventLoopGroup group = new NioEventLoopGroup(1); - - // Sets up embedded channel. - setup("", makeBootstrap(group), false); - setupChannel(initialProtocol); + public void testBasic_redirectHost() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); - // Initializes LocalAddress with unique String. - LocalAddress address = new LocalAddress(TARGET_HOST); - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); + //store future + ChannelFuture future = actionHandler.getFuture(); channel.writeOutbound(msg); - // Path that we test WebWhoisActionHandler uses. - String path = "/test"; - // Sets up the local server that the handler will be redirected to. - TestServer.webWhoisServer(group, address, "", TARGET_HOST, path); + channel.writeInbound(originalResponse); - FullHttpResponse response = - new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + TARGET_HOST + path, true)); + ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); - //checks that future has not been set to successful or a failure - assertThat(future.isDone()).isFalse(); + //gets changed protocol + Protocol newProtocol = newAction.protocol(); - channel.writeInbound(response); + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); + assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); + } - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); + @Test + public void testAdvanced_responseOk() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", TARGET_HOST, group); + + //stores future + ChannelFuture future = probingAction.call(); + + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + } + + @Test + public void testAdvanced_responseFailure() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", TARGET_HOST, group); + + //stores future + ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } + } + From e2079755743ca1b3af18fdb7b0a4cfe32967a8df Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 222/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 +++++++++----- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/ProbingSequence.java | 1 - .../monitoring/blackbox/ProbingStep.java | 7 +--- .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 - .../monitoring/blackbox/Tokens/Token.java | 4 +- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../monitoring/blackbox/WebWhoisModule.java | 2 +- .../exceptions/EppClientException.java | 29 ------------- .../blackbox/exceptions/FailureException.java | 1 - .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++- .../handlers/WebWhoisMessageHandler.java | 22 +++++++++- .../blackbox/messages/HttpRequestMessage.java | 41 +++++++++++++------ .../messages/HttpResponseMessage.java | 26 ++++++++---- .../messages/OutboundMessageType.java | 1 - .../blackbox/TestServers/TestServer.java | 16 +++++++- .../blackbox/TestServers/WebWhoisServer.java | 18 +++++++- 20 files changed, 145 insertions(+), 86 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6387207fea4..2eb90a1d6c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -119,4 +119,3 @@ public String toString() { } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 5bad5abf6bf..80b04a3d0c9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.exceptions.EppClientException; import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; import io.netty.channel.local.LocalAddress; -import java.io.IOException; + import java.util.function.Consumer; import org.joda.time.Duration; @@ -164,7 +162,4 @@ public String toString() { message(), parent); } - } - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 5e08173948e..3ceeeb8ecad 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -68,4 +68,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dba905c0e49..7200a1877e2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -197,4 +197,4 @@ static SslClientInitializer provideSslClientInitializer(SslPro } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 016c3eb32c7..84b77f89dad 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -19,4 +19,3 @@ * channel pipeline */ public interface InboundMessageType {} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 4afc5d95ba7..0acf223eb9e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; @@ -8,6 +22,11 @@ import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; +/** + * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} + * in case of reuse for redirection + */ public class WebWhoisMessageHandler extends MessageHandler { private HttpRequestMessage request; @@ -15,6 +34,7 @@ public class WebWhoisMessageHandler extends MessageHandler { @Inject public WebWhoisMessageHandler() {} + /** Retains {@link HttpRequestMessage} and calls super write method*/ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { request = (HttpRequestMessage) msg; @@ -23,9 +43,9 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) } + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - FullHttpResponse originalResponse = (FullHttpResponse) msg; InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..b06938d80a1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +31,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,16 +38,19 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + + request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + + return finalRequest; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..283b14440ac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,7 +33,7 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); @@ -26,13 +43,8 @@ public static HttpResponseMessage fromResponse(FullHttpResponse response) { else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); return finalResponse; } - - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index ba50d0707ec..e393e47ff46 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -19,4 +19,3 @@ * channel pipeline */ public interface OutboundMessageType {} - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 67e2cb7165d..a4474b6b8b5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static com.google.common.truth.Truth.assertThat; @@ -20,7 +34,7 @@ import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { private LocalAddress localAddress; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index ab9997b6c68..06b19ea3607 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -20,10 +34,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - * It will either redirect the client to the correct location if given the + *

It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location + * an unexpected host location

*/ public class WebWhoisServer extends TestServer { From 79f155273e0d946e02e3a7a667f57ec61663854f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 223/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 --- .../monitoring/blackbox/NewChannelAction.java | 144 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProberModule.java | 80 ++--- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingSequence.java | 130 ++++----- .../monitoring/blackbox/ProbingStep.java | 147 +++++----- .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/Protocol.java | 17 +- .../monitoring/blackbox/TokenModule.java | 35 --- .../monitoring/blackbox/Tokens/Token.java | 47 --- .../blackbox/Tokens/WebWhoisToken.java | 54 ---- .../monitoring/blackbox/WebWhoisModule.java | 169 ++++++----- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/ActionHandler.java | 105 +++++-- .../blackbox/handlers/MessageHandler.java | 24 -- .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../handlers/WebWhoisMessageHandler.java | 17 +- .../blackbox/messages/HttpRequestMessage.java | 46 ++- .../messages/HttpResponseMessage.java | 14 +- .../messages/OutboundMessageType.java | 11 +- .../monitoring/blackbox/tokens/Token.java | 43 +-- .../blackbox/tokens/WebWhoisToken.java | 62 ++-- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 32 files changed, 713 insertions(+), 973 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 73bd9127852..0daaf16ded4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,99 +14,59 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; import javax.inject.Singleton; +import org.joda.time.Duration; /** - * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} - * - *

Provides

+ * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores + * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. */ @Module public class ProberModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; + /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + private static final Duration DEFAULT_DURATION = new Duration(4000L); + + /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides - @HttpWhoisProtocol - ProbingSequence provideHttpWhoisSequence( - @HttpWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpsWhoisProtocol - ProbingSequence provideHttpsWhoisSequence( - @HttpsWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return httpWhoIsPort; - } - - @Provides - @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return httpsWhoIsPort; + @Singleton + Duration provideDuration() { + return DEFAULT_DURATION; } + /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - ImmutableMap providePortToProtocolMap( - Set protocolSet) { - return Maps.uniqueIndex(protocolSet, Protocol::port); + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - - + /** Root level {@link Component} that provides each {@link ProbingSequence}. */ @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, - TokenModule.class }) public interface ProberComponent { - @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); - - @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); - - ImmutableMap providePortToProtocolMap(); - - @WebWhoisProtocol Token provideWebWhoisToken(); + //Standard WebWhois sequence + @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2eb90a1d6c3..2dbf48256f9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,108 +14,100 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} - * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ - private EventLoopGroup eventGroup; + /**Each {@link ProbingSequence} requires a start token to begin running. */ + private Token startToken; - /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ - private Bootstrap bootstrap; - - public Bootstrap getBootstrap() { - return bootstrap; - } - - public void start(Token token) { - // calls the first step with input token; - firstStep.accept(token); + public void start() { + // calls the first step with startToken; + firstStep.accept(startToken); } /** - * {@link Builder} which takes in {@link ProbingStep}s - * - * @param Same specified {@code C} for overall {@link ProbingSequence} + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. */ - public static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstSequenceStep; - private EventLoopGroup eventLoopGroup; - private Class classType; - - Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public static class Builder { + + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstRepeatedStep; + private Bootstrap bootstrap; + private Token startToken; + + /** + * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. + * + *

Must be called before adding {@link ProbingStep.Builder}s.

+ */ + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } + + /** Adds start token that activate {@link ProbingSequence}. */ + public Builder addToken(Token token) { + startToken = token; return this; } - Builder addStep(ProbingStep step) { - if (currentStep == null) { + /** + * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * built, and pointed to by the previous {@link ProbingStep} added. + */ + public Builder addStep(ProbingStep.Builder stepBuilder) { + assert (bootstrap != null); + ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + + if (currentStep == null) firstStep = step; - } else { + else currentStep.nextStep(step); - } + currentStep = step; return this; } - /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ - Builder makeFirstRepeated() { - firstSequenceStep = currentStep; - return this; - } - /** Set the class to be the same as {@code C} */ - public Builder setClass(Class classType) { - this.classType = classType; + /** We take special note of the first repeated step. */ + public Builder markFirstRepeated() { + firstRepeatedStep = currentStep; return this; } - public ProbingSequence build() { - currentStep.nextStep(firstSequenceStep); + /** + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and + * calls private constructor to create {@link ProbingSequence}. + */ + public ProbingSequence build() { + if (firstRepeatedStep == null) + firstRepeatedStep = firstStep; + + currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); - return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + return new ProbingSequence(this.firstStep, this.startToken); } - } - /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ - private void setParents() { - ProbingStep currentStep = firstStep.parent(this).nextStep(); - - while (currentStep != firstStep) { - currentStep = currentStep.parent(this).nextStep(); - } - } - private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, - Class classType) { + private ProbingSequence(ProbingStep firstStep, Token startToken) { this.firstStep = firstStep; - this.eventGroup = eventLoopGroup; - this.bootstrap = new Bootstrap() - .group(eventGroup) - .channel(classType); - setParents(); - } - - @Override - public String toString() { - return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); - + this.startToken = startToken; } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 80b04a3d0c9..d54acef325a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,152 +14,145 @@ package google.registry.monitoring.blackbox; +import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.local.LocalAddress; - import java.util.function.Consumer; import org.joda.time.Duration; /** - * Represents generator of actions performed at each step in {@link ProbingSequence} - * - * @param See {@code C} in {@link ProbingSequence} + * {@link AutoValue} class that represents generator of actions performed at each step + * in {@link ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies - * these components on each loop iteration with the consumed {@link Token} and from that, - * generates new {@link ProbingAction} to perform<./p> + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. + * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, + * generates a new {@link ProbingAction} to call.

* - *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -public abstract class ProbingStep implements Consumer { +@AutoValue +public abstract class ProbingStep implements Consumer { - public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); - protected static final Duration DEFAULT_DURATION = new Duration(2000L); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - protected LocalAddress address = DEFAULT_ADDRESS; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ private boolean isLastStep = false; - private ProbingStep nextStep; - private ProbingSequence parent; + private ProbingStep nextStep; - protected Duration duration; + abstract Duration duration(); + abstract Protocol protocol(); + abstract OutboundMessageType messageTemplate(); + abstract Bootstrap bootstrap(); - protected final Protocol protocol; - protected final OutboundMessageType message; - protected ProbingStep(Protocol protocol, OutboundMessageType message) { - this.protocol = protocol; - this.message = message; - } + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder setDuration(Duration value); - private OutboundMessageType message() { - return message; - } + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); - Protocol protocol() { - return protocol; + public abstract ProbingStep build(); } + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - ProbingStep parent(ProbingSequence parent) { - this.parent = parent; - return this; - } - - /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ private ProbingAction generateAction(Token token) throws InternalException { - ProbingAction generatedAction; - - OutboundMessageType message = token.modifyMessage(message()); - - //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction - if (protocol().persistentConnection() && token.channel() != null) { - generatedAction = ExistingChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .channel(token.channel()) - .build(); - } else { - generatedAction = NewChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .bootstrap(parent.getBootstrap()) - .address(address) - .build(); - - } - return generatedAction; + OutboundMessageType message = token.modifyMessage(messageTemplate()); + ProbingAction.Builder probingActionBuilder = ProbingAction.builder() + .setDelay(duration()) + .setProtocol(protocol()) + .setOutboundMessage(message) + .setHost(token.getHost()) + .setBootstrap(bootstrap()); + + if (token.channel() != null) + probingActionBuilder.setChannel(token.channel()); + + return probingActionBuilder.build(); } - /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } @Override public void accept(Token token) { - ProbingAction nextAction; + ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - nextAction = generateAction(token); + currentAction = generateAction(token); } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - //If the next step maintains the connection, pass on the channel from this - if (protocol().persistentConnection()) { - token.channel(nextAction.channel()); - } + //call the created action - ChannelFuture future = nextAction.call(); + ChannelFuture future; + + try { + future = currentAction.call(); + + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Performed"); + nextStep.accept(generateNextToken(token)); + return; + } + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - nextStep.accept(generateNextToken(token)); + //If the next step maintains the connection, pass on the channel from this } else { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + token.setChannel(currentAction.channel()); + + nextStep.accept(generateNextToken(token)); + + }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n" + - "and parent sequence: %s", + "OutboundMessage: %s\n", protocol(), - message(), - parent); + messageTemplate().getClass().getName()); } + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 3ceeeb8ecad..ef52cb9c4bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -17,14 +17,18 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import io.netty.channel.ChannelHandler; +import io.netty.util.AttributeKey; import javax.inject.Provider; /** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. */ @AutoValue public abstract class Protocol { + /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + abstract String name(); public abstract int port(); @@ -35,8 +39,6 @@ public abstract class Protocol { /** Boolean that notes if connection associated with Protocol is persistent.*/ abstract boolean persistentConnection(); - public abstract Builder toBuilder(); - public static Builder builder() { return new AutoValue_Protocol.Builder(); } @@ -45,14 +47,13 @@ public static Builder builder() { @AutoValue.Builder public abstract static class Builder { - public abstract Builder name(String value); + public abstract Builder setName(String value); - public abstract Builder port(int num); + public abstract Builder setPort(int num); - public abstract Builder handlerProviders( - ImmutableList> providers); + public abstract Builder setHandlerProviders(ImmutableList> providers); - public abstract Builder persistentConnection(boolean value); + public abstract Builder setPersistentConnection(boolean value); public abstract Protocol build(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 7200a1877e2..dcc9635beaa 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,62 +17,86 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; -import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandler; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - final static String DOMAIN_SUFFIX = "whois.nic."; + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + private static final String DOMAIN_PREFIX = "whois.nic."; + + /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + private static final int maximumMessageLengthBytes = 512 * 1024; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - - - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - - + /** {@link Provides} standard WebWhois sequence. */ @Provides - @HttpWhoisProtocol - static ProbingStep provideHttpWhoisProbingSequence( - @HttpWhoisProtocol Protocol httpWhoisProtocol) { - return new ProbingStepWeb<>(httpWhoisProtocol); + @WebWhoisProtocol + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, + WebWhoisToken webWhoisToken, + @WebWhoisProtocol Bootstrap bootstrap) { + + return new ProbingSequence.Builder() + .addToken(webWhoisToken) + .setBootstrap(bootstrap) + .addStep(probingStepBuilder) + .build(); } + + /** {@link Provides} only step used in WebWhois sequence. */ @Provides - @HttpsWhoisProtocol - static ProbingStep provideHttpsWhoisProbingStep( - @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { - return new ProbingStepWeb<>(httpsWhoisProtocol); + @WebWhoisProtocol + static ProbingStep.Builder provideWebWhoisStepBuilder( + @HttpWhoisProtocol Protocol httpWhoisProtocol, + HttpRequestMessage messageTemplate, + Duration duration) { + + return ProbingStep.builder() + .setProtocol(httpWhoisProtocol) + .setMessageTemplate(messageTemplate) + .setDuration(duration); } - + /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides @HttpWhoisProtocol @@ -80,28 +104,14 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpProtocolForSet( - @HttpWhoisProtocol int httpWhoisPort, - @HttpWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTP_PROTOCOL_NAME) + .setPort(httpWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } - + /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ @Singleton @Provides @HttpsWhoisProtocol @@ -109,40 +119,28 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpsProtocolForSet( - @HttpsWhoisProtocol int httpsWhoisPort, - @HttpsWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTPS_PROTOCOL_NAME) + .setPort(httpsWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } + /** {@link Provides} the prefix where we probe: "prefix.tld". */ @Provides - @WebWhoisProtocol - String provideHttpWhoisHost() { - return "app"; + @Named("Web-WHOIS-Prefix") + String provideWhoisPrefix() { + return DOMAIN_PREFIX; } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -151,13 +149,14 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -167,33 +166,57 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } + @Provides + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); + } + + @Provides + static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { + return new HttpObjectAggregator(maxContentLength); + } + + /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + @Provides + @HttpsWhoisProtocol + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); + } + /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + @Singleton @Provides @WebWhoisProtocol - static MessageHandler provideMessageHandler() { - return new WebWhoisMessageHandler(); + static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + return new Bootstrap() + .group(eventLoopGroup) + .channel(NioSocketChannel.class); } @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); + @WebWhoisProtocol + int provideMaximumMessageLengthBytes() { + return maximumMessageLengthBytes; } + /** {@link Provides} the list of top level domains to be probed */ + @Singleton @Provides - static HttpObjectAggregator provideHttpObjectAggregator() { - return new HttpObjectAggregator(1048576); + @WebWhoisProtocol + ImmutableList provideTopLevelDomains() { + return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); } @Provides - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index 776a231d6dd..be3d725c833 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,10 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when the action - * performed failed due to an issue in the connection with the server. + * Base exception class for all instances when the status of the action performed is ERROR. */ -public class ConnectionException extends UndeterminedStateException { +public class ConnectionException extends Exception { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index c3622e1b810..2e155b40afd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,10 +14,11 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.ChannelFuture; @@ -26,17 +27,18 @@ import io.netty.channel.SimpleChannelInboundHandler; /** - * Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, - * as it should only be passed in messages that implement the {@link InboundMessageType} interface. + *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link - * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. - * Second, it stores the {@link OutboundMessageType} passed down the pipeline, so that subclasses - * can use that information for their own processes. Lastly, with any exception thrown, the - * connection is closed, and the ProbingAction governing this channel is informed of the error. - * Subclasses specify further work to be done for specific kinds of channel pipelines. + *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed + * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} + * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * + *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -48,33 +50,41 @@ public enum ResponseType {SUCCESS, FAILURE, ERROR} /** Status of response for current {@link ActionHandler} instance */ private static ResponseType status; + /** {@link ChannelPromise} that informs {@link google.registry.monitoring.blackbox.ProbingAction} if response has been received. */ protected ChannelPromise finished; - /** - * Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized - * {@link ChannelPromise} - */ + /** Returns initialized {@link ChannelPromise} to {@link google.registry.monitoring.blackbox.ProbingAction}.*/ public ChannelFuture getFuture() { return finished; } - /** Initializes new {@link ChannelPromise} */ + /** Initializes the same {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { // Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } + /** Initializes the same {@link ChannelPromise} in case current channel is reused (usually for EPP).*/ + public void resetFuture() { + finished = finished.channel().newPromise(); + } + + /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { - //simply marks finished as success + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { + status = ResponseType.SUCCESS; - finished.setSuccess(); + + if (!finished.isSuccess()) { + finished.setSuccess(); + } } /** - * Logs the channel and pipeline that caused error, closes channel, then informs {@link - * ProbingAction} listeners of error + * Logs the channel and pipeline that caused error, closes channel, then informs + * {@link google.registry.monitoring.blackbox.ProbingAction} listeners of error. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { @@ -83,27 +93,62 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", ctx.channel().toString(), ctx.channel().pipeline().toString())); - - if (ResponseException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + if (cause instanceof ResponseException) { + //On ResponseException, we know the response is a failure. As a result, + //we set the status to FAILURE, then inform the MetricsHandler of this status = ResponseType.FAILURE; + + //Since it wasn't a success, we still want to log to see what caused the FAILURE logger.atInfo().log(cause.getMessage()); + + //As always, inform the ProbingStep that we successfully completed this action finished.setSuccess(); - } else if (ServerSideException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + + } else if (cause instanceof ConnectionException) { + //On ConnectionException, we know the response type is an error. As a result, + //we set the status to ERROR, then inform the MetricsHandler of this status = ResponseType.ERROR; + + //Since it wasn't a success, we still log what caused the ERROR logger.atInfo().log(cause.getMessage()); finished.setSuccess(); - } else if (InternalException.class.isInstance(cause)){ + + //As this was an ERROR in the connection, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + } else if (cause instanceof InternalException){ + //For an internal error, metrics should not be collected, so we log what caused this, and + //inform the ProbingStep the Prober had an internal error on this action logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); + + + //As this was an internal error, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } else { - finished.setFailure(cause); + //In the case of any other kind of error, we assume it is some type of connection ERROR, + //so we treat it as such: + + status = ResponseType.ERROR; + + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - //due to failure, close channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + + } + + /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ + @VisibleForTesting + ResponseType getStatus() { + return status; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index ac844ac99df..919006592ea 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -89,8 +90,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); - Protocol protocol = action.protocol(); + Protocol protocol = channel.attr(PROTOCOL_KEY).get(); + String host = channel.attr(REMOTE_ADDRESS_KEY).get(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -103,7 +104,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), action.host(), protocol.port()); + .newHandler(channel.alloc(), host, protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 0acf223eb9e..58c395ad86e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -17,37 +17,36 @@ import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; /** - * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection + * in case of reuse for redirection. */ -public class WebWhoisMessageHandler extends MessageHandler { - - private HttpRequestMessage request; +public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method*/ + /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - request = (HttpRequestMessage) msg; + HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; - InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); + HttpResponseMessage response = new HttpResponseMessage(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b06938d80a1..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,19 +19,30 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); @@ -39,18 +50,29 @@ public HttpRequestMessage setUri(String path) { } /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; - ByteBuf buf = request.content(); + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; - request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + } else { + throw new IllegalArgumentException(); + } + } - return finalRequest; + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 283b14440ac..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -34,17 +34,9 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index e393e47ff46..c7ba8454ecd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,8 +14,17 @@ package google.registry.monitoring.blackbox.messages; +import google.registry.monitoring.blackbox.exceptions.InternalException; + /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in * channel pipeline */ -public interface OutboundMessageType {} +public interface OutboundMessageType { + + /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + public OutboundMessageType modifyMessage(String... args) throws InternalException; + + /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + public String name(); +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index b10c45dae8a..dd1882b5686 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,58 +14,41 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.ProbingSequence; -import google.registry.monitoring.blackbox.ProbingStep; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} in a single loop of a - * {@link ProbingSequence}. + * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} + * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes on channel that remains unchanged within a - * loop of the sequence.

+ * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop * in the sequence.

*/ public abstract class Token { - /** - * {@link Channel} that always starts out as null. Once a persistent connection is made (such as - * EPP), that channel is stored in the token and passed on to later steps in the sequence until a - * new loop begins. - */ + /** {@link Channel} that always starts out as null. */ protected Channel channel; - /** - * Obtains next {@link Token} for next loop in sequence. - */ + /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); - /** - * String corresponding to host that is relevant for loop in sequence. - */ - public abstract String host(); + /** String corresponding to host that is relevant for loop in sequence. */ + public abstract String getHost(); - /** - * Modifies the {@link OutboundMessageType} in the manner necessary for each loop - */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) - throws UndeterminedStateException; + /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; - /** - * Set method for {@code channel} - */ + /** Set method for {@code channel} */ public void setChannel(Channel channel) { this.channel = channel; } - /** - * Get method for {@code channel}. - */ + /** Get method for {@code channel}. */ public Channel channel() { return this.channel; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 3ff852f3556..2847e5ce0eb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,67 +16,59 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; +import java.util.List; import javax.inject.Inject; +import javax.inject.Named; /** * {@link Token} subtype designed for WebWhois sequence. * *

Between loops of a WebWhois sequence the only thing changing is the tld we - * are probing. As a result, we maintain the list of {@code topLevelDomains} and on each call to - * next, have our index looking at the next {@code topLevelDomain}.

+ * are probing. As a result, we maintain the list of {@code topLevelDomains} and + * on each call to next, have our index looking at the next {@code topLevelDomain}.

*/ public class WebWhoisToken extends Token { - /** - * For each top level domain (tld), we probe "prefix.tld". - */ - private static final String PREFIX = "whois.nic."; + /** For each top level domain (tld), we probe "prefix.tld". */ + private final String prefix; - /** - * {@link ImmutableList} of all top level domains to be probed. - */ - private final Iterator topLevelDomainsIterator; + /** {@link ImmutableList} of all top level domains to be probed. */ + private final ImmutableList topLevelDomains; - /** - * Current index of {@code topLevelDomains} that represents tld we are probing. - */ - private String currentDomain; + /** Current index of {@code topLevelDomains} that represents tld we are probing. */ + private int domainsIndex; @Inject - public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken( + @Named("Web-WHOIS-Prefix") String prefix, + @WebWhoisProtocol ImmutableList topLevelDomains) { - topLevelDomainsIterator = topLevelDomains.iterator(); - currentDomain = topLevelDomainsIterator.next(); + domainsIndex = 0; + this.prefix = prefix; + this.topLevelDomains = topLevelDomains; } - /** - * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. - */ + /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + domainsIndex += 1; + domainsIndex %= topLevelDomains.size(); return this; } - /** - * Modifies message to reflect the new host coming from the new top level domain. - */ + /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) - throws UndeterminedStateException { - return original.modifyMessage(host()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { + return original.modifyMessage(getHost()); } - /** - * Returns host as the concatenation of fixed {@code prefix} and current value of {@code - * topLevelDomains}. - */ + /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String host() { - return PREFIX + currentDomain; + public String getHost() { + return prefix + topLevelDomains.get(domainsIndex); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 224/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- prober/.gitignore | 1 + .../registry/monitoring/blackbox/Prober.java | 9 +- .../monitoring/blackbox/ProberModule.java | 15 +- .../monitoring/blackbox/ProbingAction.java | 161 ++++++------- .../monitoring/blackbox/ProbingSequence.java | 24 +- .../monitoring/blackbox/ProbingStep.java | 49 ++-- .../monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 49 ++-- .../exceptions/ConnectionException.java | 5 +- .../blackbox/exceptions/FailureException.java | 16 +- .../exceptions/InternalException.java | 30 --- .../exceptions/ResponseException.java | 29 --- .../UndeterminedStateException.java | 5 +- .../blackbox/handlers/ActionHandler.java | 102 ++------ .../handlers/WebWhoisActionHandler.java | 51 ++-- .../blackbox/messages/HttpRequestMessage.java | 4 +- .../messages/HttpResponseMessage.java | 6 +- .../messages/OutboundMessageType.java | 7 +- .../monitoring/blackbox/tokens/Token.java | 20 +- .../blackbox/tokens/WebWhoisToken.java | 32 ++- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../blackbox/ProbingActionTest.java | 57 ++--- .../blackbox/ProbingSequenceTest.java | 124 ++++++---- .../monitoring/blackbox/ProbingStepTest.java | 225 +++++++++--------- .../monitoring/blackbox/TestUtils.java | 84 +++++-- .../monitoring/blackbox/TokenTest.java | 19 +- .../blackbox/handlers/TestActionHandler.java | 8 +- .../handlers/WebWhoisActionHandlerTest.java | 199 +++++++--------- 32 files changed, 657 insertions(+), 680 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/.gitignore b/prober/.gitignore index 89f9ac04aac..77b1e2de2de 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1 +1,2 @@ out/ +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..307afd34d81 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +29,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 0daaf16ded4..1db97d1b581 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,14 +14,18 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.Set; import javax.inject.Singleton; import org.joda.time.Duration; @@ -33,7 +37,7 @@ public class ProberModule { /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = new Duration(4000L); + private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @@ -42,6 +46,12 @@ EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + @Provides + @Singleton + Class provideChannelClass() { + return NioSocketChannel.class; + } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides @Singleton @@ -51,6 +61,7 @@ Duration provideDuration() { /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides + @Singleton static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; @@ -66,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); + Set provideAllSequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..67494dd5f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,20 +14,25 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; @@ -64,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -79,20 +87,43 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - public abstract SocketAddress address(); - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } /** * The method that performs the work of the actual action. @@ -104,7 +135,7 @@ public abstract class ProbingAction implements Callable { * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -117,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -130,60 +161,37 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -201,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -212,40 +226,30 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract Optional address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + System.out.println("test"); + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -259,14 +263,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -284,7 +285,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2dbf48256f9..91c4165c068 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -49,32 +49,18 @@ public static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; private ProbingStep firstRepeatedStep; - private Bootstrap bootstrap; - private Token startToken; - /** - * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. - * - *

Must be called before adding {@link ProbingStep.Builder}s.

- */ - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } + private Token startToken; - /** Adds start token that activate {@link ProbingSequence}. */ - public Builder addToken(Token token) { - startToken = token; - return this; + public Builder(Token startToken) { + this.startToken = startToken; } /** - * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, * built, and pointed to by the previous {@link ProbingStep} added. */ - public Builder addStep(ProbingStep.Builder stepBuilder) { - assert (bootstrap != null); - ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + public Builder addStep(ProbingStep step) { if (currentStep == null) firstStep = step; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index d54acef325a..ca980100067 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,8 +16,8 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; @@ -37,16 +37,22 @@ @AutoValue public abstract class ProbingStep implements Consumer { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ - private boolean isLastStep = false; + protected boolean isLastStep = false; private ProbingStep nextStep; + /** Time delay duration between actions. */ abstract Duration duration(); + + /** {@link Protocol} type for this step. */ abstract Protocol protocol(); + + /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ abstract OutboundMessageType messageTemplate(); + + /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ abstract Bootstrap bootstrap(); @@ -80,17 +86,18 @@ ProbingStep nextStep() { } /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws InternalException { + private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) .setProtocol(protocol()) .setOutboundMessage(message) - .setHost(token.getHost()) - .setBootstrap(bootstrap()); + .setHost(token.host()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); + else + probingActionBuilder.setBootstrap(bootstrap()); return probingActionBuilder.build(); } @@ -101,44 +108,58 @@ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } + /** + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. + * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

+ */ @Override public void accept(Token token) { ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - //call the created action ChannelFuture future; - try { + //call the generated action future = currentAction.call(); - - } catch(InternalException e) { + } catch(UndeterminedStateException e) { + //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); + + //Move on to next step in ProbingSequence nextStep.accept(generateNextToken(token)); return; } - //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - //If the next step maintains the connection, pass on the channel from this + } else { + //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index ef52cb9c4bf..624f08fd4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -29,7 +29,7 @@ public abstract class Protocol { /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - abstract String name(); + public abstract String name(); public abstract int port(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dcc9635beaa..c5e41fea38b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,6 +18,7 @@ import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,6 +27,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; @@ -44,11 +46,10 @@ @Module public class WebWhoisModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - private static final String DOMAIN_PREFIX = "whois.nic."; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; + private static final String HTTP_PROTOCOL_NAME = "http"; + private static final String HTTPS_PROTOCOL_NAME = "https"; /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; @@ -68,16 +69,14 @@ public class WebWhoisModule { /** {@link Provides} standard WebWhois sequence. */ @Provides - @WebWhoisProtocol + @Singleton + @IntoSet ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, - WebWhoisToken webWhoisToken, - @WebWhoisProtocol Bootstrap bootstrap) { + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { - return new ProbingSequence.Builder() - .addToken(webWhoisToken) - .setBootstrap(bootstrap) - .addStep(probingStepBuilder) + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) .build(); } @@ -85,15 +84,18 @@ ProbingSequence provideWebWhoisSequence( /** {@link Provides} only step used in WebWhois sequence. */ @Provides @WebWhoisProtocol - static ProbingStep.Builder provideWebWhoisStepBuilder( + static ProbingStep provideWebWhoisStep( @HttpWhoisProtocol Protocol httpWhoisProtocol, + @WebWhoisProtocol Bootstrap bootstrap, HttpRequestMessage messageTemplate, Duration duration) { return ProbingStep.builder() .setProtocol(httpWhoisProtocol) + .setBootstrap(bootstrap) .setMessageTemplate(messageTemplate) - .setDuration(duration); + .setDuration(duration) + .build(); } /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @@ -126,13 +128,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** {@link Provides} the prefix where we probe: "prefix.tld". */ - @Provides - @Named("Web-WHOIS-Prefix") - String provideWhoisPrefix() { - return DOMAIN_PREFIX; - } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @@ -187,10 +182,12 @@ static SslClientInitializer provideSslClientInitializer(SslPro @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + static Bootstrap provideBootstrap( + EventLoopGroup eventLoopGroup, + Class channelClass){ return new Bootstrap() .group(eventLoopGroup) - .channel(NioSocketChannel.class); + .channel(channelClass); } @Provides @@ -210,13 +207,13 @@ ImmutableList provideTopLevelDomains() { @Provides @HttpWhoisProtocol int provideHttpWhoisPort() { - return httpWhoIsPort; + return HTTP_WHOIS_PORT; } @Provides @HttpsWhoisProtocol int provideHttpsWhoisPort() { - return httpsWhoIsPort; + return HTTPS_WHOIS_PORT; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index be3d725c833..adb833ec629 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,9 +15,10 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is ERROR. + * Subclass of {@link UndeterminedStateException} that represents all instances when + * the action performed failed due to an issue in the connection with the server. */ -public class ConnectionException extends Exception { +public class ConnectionException extends UndeterminedStateException { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 84b77f89dad..36687e7ac82 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,10 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.messages; +package google.registry.monitoring.blackbox.exceptions; /** - * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in - * channel pipeline + * Base exception class for all instances when the status of the action performed is FAILURE. */ -public interface InboundMessageType {} +public class FailureException extends Exception { + + public FailureException(String msg) { + super(msg); + } + + public FailureException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java index d7127717d52..c155d695c7f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java @@ -15,8 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails before we can determine - * the state of the result, meaning the status is recorded as ERROR. + * Base exception class for all instances when the action performed fails + * before we can determine the state of the result, meaning the status + * is recorded as ERROR. */ public class UndeterminedStateException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 2e155b40afd..247424243cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,17 +14,15 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; /** *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline @@ -33,7 +31,7 @@ * messages that implement the {@link InboundMessageType} interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

@@ -44,111 +42,59 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); - - } else if (cause instanceof InternalException){ - //For an internal error, metrics should not be collected, so we log what caused this, and - //inform the ProbingStep the Prober had an internal error on this action - logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - - //As this was an internal error, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } else { - //In the case of any other kind of error, we assume it is some type of connection ERROR, - //so we treat it as such: - - status = ResponseType.ERROR; + //On UndeterminedStateException, we know the response type is an error. - logger.atInfo().log(cause.getMessage()); - finished.setSuccess(); + //Since it wasn't a success, we still log what caused the ERROR + logger.atWarning().log(cause.getMessage()); + finished.setFailure(cause); + //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } - - /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ - @VisibleForTesting - ResponseType getStatus() { - return status; - } -} - +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 69d5b7f1603..1ec4e314813 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -22,13 +22,12 @@ import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -62,27 +61,17 @@ public class WebWhoisActionHandler extends ActionHandler { /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ private final HttpRequestMessage requestMessage; - /** Default port for http. */ - private int httpPort; - - /** default port for https. */ - private int httpsPort; - @Inject public WebWhoisActionHandler( @WebWhoisProtocol Bootstrap bootstrap, @HttpWhoisProtocol Protocol httpWhoisProtocol, @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage, - @HttpWhoisProtocol int httpPort, - @HttpsWhoisProtocol int httpsPort) { + HttpRequestMessage requestMessage) { this.bootstrap = bootstrap; this.httpWhoisProtocol = httpWhoisProtocol; this.httpsWhoisProtocol = httpsWhoisProtocol; this.requestMessage = requestMessage; - this.httpPort = httpPort; - this.httpsPort = httpsPort; } @@ -93,7 +82,7 @@ public WebWhoisActionHandler( */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -112,7 +101,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -123,12 +112,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; - if (newPort == httpPort) { + if (url.getProtocol().equals(httpWhoisProtocol.name())) { newProtocol = httpWhoisProtocol; - } else if (newPort == httpsPort) { + } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -143,34 +132,38 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) .setHost(newHost) .build(); - //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); - //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..b4c01d06a8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,12 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..f1b2d6ac6a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -25,11 +25,7 @@ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { - super(version, status); - } - - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index c7ba8454ecd..d8a28c25dbd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,7 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in @@ -23,8 +23,9 @@ public interface OutboundMessageType { /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - public OutboundMessageType modifyMessage(String... args) throws InternalException; + OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - public String name(); + @Override + String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dd1882b5686..dab5851e8d8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,16 +14,18 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.ProbingSequence; +import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} - * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} + * in a single loop of a {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * in a {@link ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -31,17 +33,21 @@ */ public abstract class Token { - /** {@link Channel} that always starts out as null. */ + /** + * {@link Channel} that always starts out as null. Once a persistent connection + * is made (such as EPP), that channel is stored in the token and passed on to + * later steps in the sequence until a new loop begins. + */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String getHost(); + public abstract String host(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 2847e5ce0eb..bb06ee89db6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import javax.inject.Inject; import javax.inject.Named; @@ -33,42 +33,38 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final String prefix; + private final static String PREFIX = "whois.nic."; /** {@link ImmutableList} of all top level domains to be probed. */ - private final ImmutableList topLevelDomains; + private final Iterator topLevelDomainsIterator; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private int domainsIndex; + private String currentDomain; @Inject - public WebWhoisToken( - @Named("Web-WHOIS-Prefix") String prefix, - @WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { - domainsIndex = 0; - this.prefix = prefix; - this.topLevelDomains = topLevelDomains; + topLevelDomainsIterator = topLevelDomains.iterator(); + currentDomain = topLevelDomainsIterator.next(); } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - domainsIndex += 1; - domainsIndex %= topLevelDomains.size(); + currentDomain = topLevelDomainsIterator.next(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { - return original.modifyMessage(getHost()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + return original.modifyMessage(host()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String getHost() { - return prefix + topLevelDomains.get(domainsIndex); + public String host() { + return PREFIX + currentDomain; } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v(builder() - .bootstrap(bootstrap) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") - .address(address) + newChannelAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) .build(); } private void setupChannel() { channel = new EmbeddedChannel(); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ExistingChannelAction.builder() - .channel(channel) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") + existingChannelAction = ProbingAction.builder() + .setChannel(channel) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") .build(); } @Test - public void testBehavior_existingChannel() { + public void testBehavior_existingChannel() throws UndeterminedStateException { //setup setupChannel(); setupExistingChannelProtocol(); - setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); + setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -147,6 +149,7 @@ public void testBehavior_existingChannel() { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -156,9 +159,9 @@ public void testBehavior_existingChannel() { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - setupNewChannelAction(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + setupNewChannelAction(); ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 02599bcb51a..2a8d5ebe233 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,59 +1,86 @@ -// Copyright 2019 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; +import static google.registry.testing.JUnitBackports.assertThrows; +import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import org.junit.Before; +import io.netty.bootstrap.Bootstrap; +import java.net.SocketAddress; +import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.Mockito; @RunWith(JUnit4.class) public class ProbingSequenceTest { - - private ProbingStep firstStep; - private ProbingStep secondStep; - private ProbingStep thirdStep; - - private Token testToken; - - private ProbingStep setupMockStep() { - ProbingStep mock = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(mock).nextStep(); - return mock; - } - - @Before - public void setup() { - firstStep = setupMockStep(); - secondStep = setupMockStep(); - thirdStep = setupMockStep(); - - testToken = Mockito.mock(Token.class); + private final static String TEST_HOST = "TEST_HOST"; + + + private Token testToken = new ProbingSequenceTestToken(); + + /** + * Custom {@link ProbingStep} subclass that acts as a mock + * step, so we can test how well {@link ProbingSequence} builds + * a linked list of {@link ProbingStep}s from their {@link Builder}s. + */ + private static class TestStep extends ProbingStep { + private String marker; + + /** We implement all abstract methods to simply return null, as we have no use for them here. */ + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ + @Override + Bootstrap bootstrap() { + return null; + } + + public TestStep(String marker) { + this.marker = marker; + } + + /** + * On a call to accept, we modify the token to reflect what the current step is, so we can get + * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated + * in order. + */ + @Override + public void accept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + if (!isLastStep) { + nextStep().accept(token); + } else { + ((TestStep)nextStep()).specialAccept(token); + } + } + + /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ + public void specialAccept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + return; + } } @Test public void testSequenceBasicConstruction_Success() { + ProbingStep firstStep = new TestStep("first"); + ProbingStep secondStep = new TestStep("second"); + ProbingStep thirdStep = new TestStep("third"); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) @@ -61,17 +88,16 @@ public void testSequenceBasicConstruction_Success() { .addStep(thirdStep) .build(); - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(thirdStep); - assertThat(thirdStep.nextStep()).isEqualTo(firstStep); - sequence.start(); - verify(firstStep, times(1)).accept(testToken); + assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); } @Test public void testSequenceAdvancedConstruction_Success() { + ProbingStep firstStep = new TestStep("first"); + ProbingStep secondStep = new TestStep("second"); + ProbingStep thirdStep = new TestStep("third"); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(thirdStep) @@ -80,13 +106,9 @@ public void testSequenceAdvancedConstruction_Success() { .addStep(firstStep) .build(); - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(firstStep); - assertThat(thirdStep.nextStep()).isEqualTo(secondStep); - sequence.start(); - verify(thirdStep, times(1)).accept(testToken); + assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index db7ec271956..7bba9d66782 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,192 +11,201 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.TestUtils.dummyStep; +import static google.registry.monitoring.blackbox.TestUtils.testStep; +import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import org.joda.time.Duration; -import org.junit.Ignore; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; import org.junit.Rule; import org.junit.Test; -import org.mockito.Mockito; -/** - * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific - * implementations - */ +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ public class ProbingStepTest { - /** - * Basic Constants necessary for tests - */ - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final int PROTOCOL_PORT = 0; - private static final String TEST_MESSAGE = "TEST_MESSAGE"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - private static final LocalAddress ADDRESS = new LocalAddress(ADDRESS_NAME); + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - /** - * Used for testing how well probing step can create connection to blackbox server - */ + /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** - * The two main handlers we need in any test pipeline used that connects to {@link NettyRule's - * server} - **/ + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** - * Creates mock {@link Token} object that returns the host and returns unchanged message when - * modifying it. - */ - private Token testToken(String host) throws UndeterminedStateException { - Token token = Mockito.mock(Token.class); - doReturn(host).when(token).host(); - doAnswer(answer -> answer.getArgument(0)).when(token) - .modifyMessage(any(OutboundMessageType.class)); - return token; + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(ADDRESS_NAME); } - @Test - public void testNewChannel() throws Exception { - // Sets up Protocol for when we create a new channel. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); + dummyStep = dummyStep(eventLoopGroup); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); + } - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) .build(); + } - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); - firstStep.nextStep(dummyStep); + //there should be no next step + assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = testToken(ADDRESS_NAME); - //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(ADDRESS); + } + + @Test + public void testNewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //checks that we have appropriately sent the write message to server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - verify(dummyStep, times(1)).accept(any(Token.class)); + assertThat(future.get()).isEqualTo(testToken); + } - //TODO - Currently, this test fails to receive outbound messages from the embedded channel, which - // we will fix in a later release. - @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - // Sets up Protocol for when a channel already exists. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) - .build(); - - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) - .build(); - - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - - firstStep.nextStep(dummyStep); - - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - - //Assures that the channel has a succeeded connectionFuture. - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = testToken(""); - doReturn(channel).when(testToken).channel(); + //setup + setupExistingProtocol(); + setupSteps(); + setupChannel(); + setupExistingChannelToken(); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message through the EmbeddedChannel - // pipeline + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); - Object msg = channel.readOutbound(); - - while (msg == null) { - msg = channel.readOutbound(); - } //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf) channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked - // as a success - verify(dummyStep, times(1)).accept(any(Token.class)); + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 8d1722c9625..68bdd0bcef0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,15 +17,15 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpMessage; @@ -37,6 +37,8 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; +import java.net.SocketAddress; +import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -141,26 +143,55 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } + + @Override + public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { + message = args[0]; + return this; + } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static class TestStep extends ProbingStep { + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .build(); - public TestStep(Protocol protocol, String testMessage, LocalAddress address) { - super(protocol, new DuplexMessageTest(testMessage)); - this.address = address; - this.duration = Duration.ZERO; - } + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { - super(protocol, new DuplexMessageTest()); - future = new DefaultPromise(eventLoopGroup.next()) {}; - duration = Duration.ZERO; + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; } @Override @@ -170,11 +201,16 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } + + @Override + public String toString() { + return "Dummy Step"; + } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - private String host; + protected String host; protected TestToken(String host) { this.host = host; @@ -190,7 +226,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String getHost() { + public String host() { return host; } @@ -221,6 +257,22 @@ public Channel channel() { } } + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..295bb809a13 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,12 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -34,21 +33,21 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); - } catch(InternalException e) { + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 518bb9ba686..3ecbdcc0d06 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,7 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws FailureException, UndeterminedStateException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 71d8d66b6c0..83d004d4555 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,17 +15,20 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; @@ -37,9 +40,7 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; @@ -65,7 +66,13 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private static final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of()) + .setName("http") + .setPersistentConnection(false) + .setPort(HTTPS_PORT) + .build(); + private LocalAddress address; private EmbeddedChannel channel; @@ -73,33 +80,39 @@ public class WebWhoisActionHandlerTest { private ProbingAction probingAction; private Provider actionHandlerProvider; - private void generateLocalAddress() { - address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + private String generateLocalAddress(String addressString) { + String modifiedAddress = addressString + System.currentTimeMillis(); + address = new LocalAddress(modifiedAddress); + return modifiedAddress; } + /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { + private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of(actionHandlerProvider)) - .persistentConnection(false) + .setName(name) + .setPort(port) + .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) + .setPersistentConnection(persistentConnection) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); + private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { + actionHandler = new WebWhoisActionHandler( + bootstrap, + STANDARD_PROTOCOL, + STANDARD_PROTOCOL, + messageTemplate + ); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - setupProbingActionBasic( - protocol, - outboundMessage, - makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -108,25 +121,23 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } /**Sets up probingAction for when testing redirection */ - private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(TARGET_HOST) - .address(DEFAULT_ADDRESS) + private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setHost(TARGET_HOST) + .setChannel(channel) .build(); } - private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(host) - .address(address) + private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(addressString) .build(); } @@ -137,10 +148,11 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); - generateLocalAddress(); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, true); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); @@ -150,7 +162,7 @@ public void testBasic_responseOk() throws Exception { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -164,12 +176,12 @@ public void testBasic_responseOk() throws Exception { } @Test - public void testBasic_responseFailure() { + public void testBasic_responseFailure_badRequest() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseBad", 0); - generateLocalAddress(); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseBad", 0, true); setupChannel(initialProtocol, msg); //stores future @@ -179,8 +191,7 @@ public void testBasic_responseFailure() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage - .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -192,15 +203,15 @@ public void testBasic_responseFailure() { assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testBasic_responseError() { + public void testBasic_responseFailure_badURL() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseError", 0); - generateLocalAddress(); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseError", 0, true); setupChannel(initialProtocol, msg); //stores future @@ -211,7 +222,7 @@ public void testBasic_responseError() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -220,28 +231,31 @@ public void testBasic_responseError() { //assesses that listener is triggered, and event is success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(future.cause() instanceof FailureException); } @Test public void testBasic_redirectCloseChannel() { //setup - HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", 0); - generateLocalAddress(); - setupChannel(initialProtocol, outboundMessage); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", 0, true); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -255,44 +269,15 @@ public void testBasic_redirectCloseChannel() { } @Test - public void testBasic_redirectHost() { - //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); - generateLocalAddress(); - setupChannel(initialProtocol, msg); - HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); - - - //store future - ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); - - - channel.writeInbound(originalResponse); - - ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); - - //gets changed protocol - Protocol newProtocol = newAction.protocol(); - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); - assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); - } - - @Test - public void testAdvanced_responseOk() { + public void testAdvanced_responseOk() throws UndeterminedStateException { //setup EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); - generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); - setupLocalServer("", TARGET_HOST, group); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); + setupActionHandler(null, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); @@ -302,21 +287,21 @@ public void testAdvanced_responseOk() { } @Test - public void testAdvanced_responseFailure() { + public void testAdvanced_responseFailure() throws UndeterminedStateException { //setup EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); - generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); - setupLocalServer("", TARGET_HOST, group); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(null, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + assertThrows(FailureException.class, future::syncUninterruptibly); } } From 94897b379489a90be9e16a16467707542cfe04af Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 225/337] Added missing license headers and JavaDoc --- .../handlers/ServerSideException.java | 29 ++++++++++ .../blackbox/messages/HttpRequestMessage.java | 53 +++++++------------ .../messages/HttpResponseMessage.java | 32 ++++++++--- 3 files changed, 74 insertions(+), 40 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..441062a9e7b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b4c01d06a8f..8fbb55c6339 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,60 +19,45 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} + * (but needs to implement {@link OutboundMessageType}) * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

+ *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion + * from {@link FullHttpRequest} to its type

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - @Override public HttpRequestMessage setUri(String path) { super.setUri(path); return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } + /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; + ByteBuf buf = request.content(); - /** Modifies headers to reflect new host and new path if applicable. */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) - setUri(args[1]); + //creates message based on content found in original request + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - return this; - } else { - throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); - } - } + //stores headers from request in finalRequest + request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); - } + return finalRequest; + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index f1b2d6ac6a7..776e7de0824 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -16,23 +16,43 @@ import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; /** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} + * (but needs to implement {@link InboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion + * from {@link FullHttpResponse} to its type

*/ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { + super(version, status); + } + + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + //creates message based on content found in original response + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + //stores headers from response in finalResponse + response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + return finalResponse; } } From ffcffe8f7d0b08324cc7a6ed3d0b63cbea16cce5 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 226/337] Minor fix in NewChannelAction JavaDoc --- .../monitoring/blackbox/NewChannelAction.java | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..1e7578d5679 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,134 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + From 050e0a315832de08a9ddd824e997b333a1dd42ce Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 227/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 22 +- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 13 +- .../registry/monitoring/blackbox/Prober.java | 24 +- .../monitoring/blackbox/ProberModule.java | 83 +++++-- .../monitoring/blackbox/ProbingAction.java | 232 +++++------------- .../monitoring/blackbox/ProbingSequence.java | 117 +++++---- .../monitoring/blackbox/ProbingStep.java | 177 +++++++------ .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 1 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 +++++ .../monitoring/blackbox/WebWhoisModule.java | 172 ++++++------- .../exceptions/EppClientException.java | 29 +++ .../exceptions/InternalException.java | 29 +++ .../exceptions/ResponseException.java | 29 +++ .../ServerSideException.java | 4 +- .../blackbox/handlers/ActionHandler.java | 86 +++---- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/WebWhoisActionHandler.java | 105 +++----- .../handlers/WebWhoisMessageHandler.java | 31 +-- .../blackbox/messages/HttpRequestMessage.java | 50 ++-- .../messages/HttpResponseMessage.java | 32 +-- .../messages/OutboundMessageType.java | 11 +- .../blackbox/ProbingActionTest.java | 57 ++--- .../blackbox/TestServers/TestServer.java | 16 +- .../blackbox/TestServers/WebWhoisServer.java | 18 +- .../monitoring/blackbox/TestUtils.java | 84 ++----- .../monitoring/blackbox/TokenTest.java | 19 +- .../blackbox/handlers/TestActionHandler.java | 8 +- .../handlers/WebWhoisActionHandlerTest.java | 210 ++++++++-------- 32 files changed, 984 insertions(+), 913 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java diff --git a/prober/build.gradle b/prober/build.gradle index 993da44655d..e48eacb8bf9 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -17,8 +17,9 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { - def deps = rootProject.dependencyMap + def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] @@ -37,9 +38,9 @@ dependencies { compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] - runtime deps['com.google.flogger:flogger-system-backend'] - runtime deps['com.google.auto.value:auto-value'] - runtime deps['io.netty:netty-tcnative-boringssl-static'] + runtime deps['com.google.flogger:flogger-system-backend'] + runtime deps['com.google.auto.value:auto-value'] + runtime deps['io.netty:netty-tcnative-boringssl-static'] testCompile deps['com.google.truth:truth'] testCompile deps['junit:junit'] @@ -47,12 +48,11 @@ dependencies { testCompile project(':third_party') //testCompile project(path: ':core', configuration: 'testRuntime') - // Include auto-value in compile until nebula-lint understands - // annotationProcessor - annotationProcessor deps['com.google.auto.value:auto-value'] - testAnnotationProcessor deps['com.google.auto.value:auto-value'] - annotationProcessor deps['com.google.dagger:dagger-compiler'] - testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] + // Include auto-value in compile until nebula-lint understands + // annotationProcessor + annotationProcessor deps['com.google.auto.value:auto-value'] + testAnnotationProcessor deps['com.google.auto.value:auto-value'] + annotationProcessor deps['com.google.dagger:dagger-compiler'] + testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -84,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -117,7 +118,7 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 307afd34d81..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,26 +14,32 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - /** Main Dagger Component */ + /** Main {@link Dagger} Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + public static void main(String[] args) { - //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 1db97d1b581..73bd9127852 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,70 +14,99 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SslProvider; import java.util.Set; import javax.inject.Singleton; -import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores - * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. + * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} + * + *

Provides

*/ @Module public class ProberModule { + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; - /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - - /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides - @Singleton - Class provideChannelClass() { - return NioSocketChannel.class; + @HttpWhoisProtocol + ProbingSequence provideHttpWhoisSequence( + @HttpWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ + @Provides - @Singleton - Duration provideDuration() { - return DEFAULT_DURATION; + @HttpsWhoisProtocol + ProbingSequence provideHttpsWhoisSequence( + @HttpsWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; + } + + @Provides + @HttpsWhoisProtocol + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } - /** Root level {@link Component} that provides each {@link ProbingSequence}. */ + @Provides + ImmutableMap providePortToProtocolMap( + Set protocolSet) { + return Maps.uniqueIndex(protocolSet, Protocol::port); + } + + + @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, + TokenModule.class }) public interface ProberComponent { - //Standard WebWhois sequence - Set provideAllSequences(); + @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); + + @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); + + ImmutableMap providePortToProtocolMap(); + + @WebWhoisProtocol Token provideWebWhoisToken(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 67494dd5f78..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,28 +14,13 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -49,7 +34,7 @@ import javax.inject.Provider; /** - * AutoValue class that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -59,25 +44,36 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

*/ -@AutoValue + public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; + - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; + } /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); + /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -90,26 +86,23 @@ public abstract class ProbingAction implements Callable { /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); - /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); + - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel + future -> finished.setSuccess(), future -> { if (!protocol().persistentConnection()) { + //If we created a new channel for this action, close the connection to the channel ChannelFuture closedFuture = channel().close(); closedFuture.addListener( f -> { @@ -124,158 +117,56 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler } ); } - /** - * The method that performs the work of the actual action. - * - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * The method that sends the {@code outboundMessage} down the channel pipeline * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. + * @return future that denotes when the action has been successfully performed */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); + @Override + public ChannelFuture call() { + + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, delay().getStandardSeconds(), TimeUnit.SECONDS); - + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } return finished; } - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ - @Override - public ChannelFuture call() throws UndeterminedStateException { - //ChannelPromise that we return - ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ - @AutoValue.Builder - public abstract static class Builder { - private Bootstrap bootstrap; - - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } - - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); + public abstract static class Builder, P extends ProbingAction> { - public abstract Builder setHost(String value); + public abstract B delay(Duration value); - public abstract Builder setChannel(Channel channel); + public abstract B outboundMessage(OutboundMessageType value); - abstract Protocol protocol(); + public abstract B protocol(Protocol value); - abstract Optional channel(); + public abstract B host(String value); - abstract String host(); + public abstract B path(String value); - abstract ProbingAction autoBuild(); + public abstract P build(); - public ProbingAction build() { - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - System.out.println("test"); - address = new LocalAddress(host()); - } - - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); - //If a channel is supplied, nothing is needed to be done - - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); - - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } - - //now we can actually build the ProbingAction - return autoBuild(); - } - } - - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); } /** @@ -285,27 +176,26 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - private static void addHandlers( + static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { channelPipeline.addLast(handlerProvider.get()); } } - - - @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n", + "host: %s\n" + + "path: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host() + host(), + path() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 91c4165c068..6387207fea4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,86 +14,109 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. + * Represents Sequence of {@link ProbingSteps} that the Prober performs in order * + * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} + * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /**Each {@link ProbingSequence} requires a start token to begin running. */ - private Token startToken; + /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ + private EventLoopGroup eventGroup; - public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ + private Bootstrap bootstrap; + + public Bootstrap getBootstrap() { + return bootstrap; + } + + public void start(Token token) { + // calls the first step with input token; + firstStep.accept(token); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * {@link Builder} which takes in {@link ProbingStep}s + * + * @param Same specified {@code C} for overall {@link ProbingSequence} */ - public static class Builder { - - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - - private Token startToken; - - public Builder(Token startToken) { - this.startToken = startToken; + public static class Builder { + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstSequenceStep; + private EventLoopGroup eventLoopGroup; + private Class classType; + + Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; + return this; } - /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, - * built, and pointed to by the previous {@link ProbingStep} added. - */ - public Builder addStep(ProbingStep step) { - - if (currentStep == null) + Builder addStep(ProbingStep step) { + if (currentStep == null) { firstStep = step; - else + } else { currentStep.nextStep(step); - + } currentStep = step; return this; } - /** We take special note of the first repeated step. */ - public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; + /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ + Builder makeFirstRepeated() { + firstSequenceStep = currentStep; + return this; + } + /** Set the class to be the same as {@code C} */ + public Builder setClass(Class classType) { + this.classType = classType; return this; } - /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and - * calls private constructor to create {@link ProbingSequence}. - */ - public ProbingSequence build() { - if (firstRepeatedStep == null) - firstRepeatedStep = firstStep; - - currentStep.nextStep(firstRepeatedStep); + public ProbingSequence build() { + currentStep.nextStep(firstSequenceStep); currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); } + } - private ProbingSequence(ProbingStep firstStep, Token startToken) { + /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ + private void setParents() { + ProbingStep currentStep = firstStep.parent(this).nextStep(); + + while (currentStep != firstStep) { + currentStep = currentStep.parent(this).nextStep(); + } + } + private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, + Class classType) { this.firstStep = firstStep; - this.startToken = startToken; + this.eventGroup = eventLoopGroup; + this.bootstrap = new Bootstrap() + .group(eventGroup) + .channel(classType); + setParents(); + } + + @Override + public String toString() { + return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index ca980100067..5bad5abf6bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,164 +14,155 @@ package google.registry.monitoring.blackbox; -import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.io.IOException; import java.util.function.Consumer; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step - * in {@link ProbingSequence}. + * Represents generator of actions performed at each step in {@link ProbingSequence} + * + * @param See {@code C} in {@link ProbingSequence} * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. - * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, - * generates a new {@link ProbingAction} to call.

+ * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies + * these components on each loop iteration with the consumed {@link Token} and from that, + * generates new {@link ProbingAction} to perform<./p> * + *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -@AutoValue -public abstract class ProbingStep implements Consumer { +public abstract class ProbingStep implements Consumer { + public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); + protected static final Duration DEFAULT_DURATION = new Duration(2000L); private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Necessary boolean to inform when to obtain next {@link Token}*/ - protected boolean isLastStep = false; - private ProbingStep nextStep; - - /** Time delay duration between actions. */ - abstract Duration duration(); - - /** {@link Protocol} type for this step. */ - abstract Protocol protocol(); - - /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ - abstract OutboundMessageType messageTemplate(); - - /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ - abstract Bootstrap bootstrap(); - + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + protected LocalAddress address = DEFAULT_ADDRESS; - @AutoValue.Builder - public static abstract class Builder { - public abstract Builder setDuration(Duration value); + /** Necessary boolean to inform when to obtain next {@link Token}*/ + private boolean isLastStep = false; + private ProbingStep nextStep; + private ProbingSequence parent; - public abstract Builder setProtocol(Protocol value); + protected Duration duration; - public abstract Builder setMessageTemplate(OutboundMessageType value); + protected final Protocol protocol; + protected final OutboundMessageType message; - public abstract Builder setBootstrap(Bootstrap value); + protected ProbingStep(Protocol protocol, OutboundMessageType message) { + this.protocol = protocol; + this.message = message; + } - public abstract ProbingStep build(); + private OutboundMessageType message() { + return message; } - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); + Protocol protocol() { + return protocol; } + void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { - OutboundMessageType message = token.modifyMessage(messageTemplate()); - ProbingAction.Builder probingActionBuilder = ProbingAction.builder() - .setDelay(duration()) - .setProtocol(protocol()) - .setOutboundMessage(message) - .setHost(token.host()); - - if (token.channel() != null) - probingActionBuilder.setChannel(token.channel()); - else - probingActionBuilder.setBootstrap(bootstrap()); - - return probingActionBuilder.build(); + ProbingStep parent(ProbingSequence parent) { + this.parent = parent; + return this; } + /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + private ProbingAction generateAction(Token token) throws InternalException { + ProbingAction generatedAction; + + OutboundMessageType message = token.modifyMessage(message()); + + //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction + if (protocol().persistentConnection() && token.channel() != null) { + generatedAction = ExistingChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .channel(token.channel()) + .build(); + } else { + generatedAction = NewChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .bootstrap(parent.getBootstrap()) + .address(address) + .build(); + + } + return generatedAction; + } - /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ + + /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

- */ @Override public void accept(Token token) { - ProbingAction currentAction; + ProbingAction nextAction; //attempt to generate new action. On error, move on to next step try { - currentAction = generateAction(token); - } catch(UndeterminedStateException e) { + nextAction = generateAction(token); + } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch(UndeterminedStateException e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; + //If the next step maintains the connection, pass on the channel from this + if (protocol().persistentConnection()) { + token.channel(nextAction.channel()); } + //call the created action + ChannelFuture future = nextAction.call(); + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - + nextStep.accept(generateNextToken(token)); } else { - //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - - if (protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n", + "OutboundMessage: %s\n" + + "and parent sequence: %s", protocol(), - messageTemplate().getClass().getName()); + message(), + parent); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 624f08fd4e9..71a2777cf5f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -69,3 +69,4 @@ public String toString() { ); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index c5e41fea38b..dba905c0e49 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,103 +17,91 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; + +import google.registry.monitoring.blackbox.handlers.MessageHandler; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; - private static final String HTTP_PROTOCOL_NAME = "http"; - private static final String HTTPS_PROTOCOL_NAME = "https"; - - /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ - private static final int maximumMessageLengthBytes = 512 * 1024; + final static String DOMAIN_SUFFIX = "whois.nic."; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpWhoisProtocol {} + @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpsWhoisProtocol {} + @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - /** {@link Provides} standard WebWhois sequence. */ + + + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + + @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { + @HttpWhoisProtocol + static ProbingStep provideHttpWhoisProbingSequence( + @HttpWhoisProtocol Protocol httpWhoisProtocol) { + return new ProbingStepWeb<>(httpWhoisProtocol); + } - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); + @Provides + @HttpsWhoisProtocol + static ProbingStep provideHttpsWhoisProbingStep( + @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { + return new ProbingStepWeb<>(httpsWhoisProtocol); } - /** {@link Provides} only step used in WebWhois sequence. */ + @Singleton @Provides - @WebWhoisProtocol - static ProbingStep provideWebWhoisStep( - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @WebWhoisProtocol Bootstrap bootstrap, - HttpRequestMessage messageTemplate, - Duration duration) { - - return ProbingStep.builder() - .setProtocol(httpWhoisProtocol) - .setBootstrap(bootstrap) - .setMessageTemplate(messageTemplate) - .setDuration(duration) + @HttpWhoisProtocol + static Protocol provideHttpWhoisProtocol( + @HttpWhoisProtocol int httpWhoisPort, + @HttpWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides - @HttpWhoisProtocol - static Protocol provideHttpWhoisProtocol( + @IntoSet + static Protocol provideHttpProtocolForSet( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTP_PROTOCOL_NAME) - .setPort(httpWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ + @Singleton @Provides @HttpsWhoisProtocol @@ -121,21 +109,40 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTPS_PROTOCOL_NAME) - .setPort(httpsWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Singleton + @Provides + @IntoSet + static Protocol provideHttpsProtocolForSet( + @HttpsWhoisProtocol int httpsWhoisPort, + @HttpsWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } + @Provides + @WebWhoisProtocol + String provideHttpWhoisHost() { + return "app"; + } + - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -144,14 +151,13 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -161,60 +167,34 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } - @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); - } - - @Provides - static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { - return new HttpObjectAggregator(maxContentLength); - } - - /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ - @Provides - @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); - } - /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ - @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap( - EventLoopGroup eventLoopGroup, - Class channelClass){ - return new Bootstrap() - .group(eventLoopGroup) - .channel(channelClass); + static MessageHandler provideMessageHandler() { + return new WebWhoisMessageHandler(); } @Provides - @WebWhoisProtocol - int provideMaximumMessageLengthBytes() { - return maximumMessageLengthBytes; + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); } - /** {@link Provides} the list of top level domains to be probed */ - @Singleton @Provides - @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); + static HttpObjectAggregator provideHttpObjectAggregator() { + return new HttpObjectAggregator(1048576); } @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return HTTP_WHOIS_PORT; + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } @Provides @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return HTTPS_WHOIS_PORT; + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 247424243cb..7898203e92d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,86 +15,88 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; /** - *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} - * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

- * - *

Subclasses specify further work to be done for specific kinds of channel pipelines.

+ *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} + * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception + * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses + * specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link ChannelPromise} that informs {@link ProbingAction} if response has been received. */ - private ChannelPromise finished; + /** Three types of responses received down pipeline */ + public enum ResponseType {SUCCESS, FAILURE, ERROR} + + /** Status of response for current {@link ActionHandler} instance */ + private static ResponseType status; + + protected ChannelPromise finished; - /** Returns initialized {@link ChannelPromise} to {@link ProbingAction}.*/ + /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ public ChannelFuture getFuture() { return finished; } - /** Initializes {@link ChannelPromise}*/ + /** Initializes new {@link ChannelPromise} */ @Override public void handlerAdded(ChannelHandlerContext ctx) { - // Once handler is added to channel pipeline, initialize channel and future for this handler + //Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } - /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { - + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + //simply marks finished as success + status = ResponseType.SUCCESS; finished.setSuccess(); } - /** - * Logs the channel and pipeline that caused error, closes channel, then informs - * {@link ProbingAction} listeners of error. - */ + /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atWarning().withCause(cause).log(String.format( + logger.atSevere().withCause(cause).log(String.format( "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", ctx.channel().toString(), ctx.channel().pipeline().toString())); - if (cause instanceof FailureException) { - //On FailureException, we know the response is a failure. - //Since it wasn't a success, we still want to log to see what caused the FAILURE + if (ResponseException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + status = ResponseType.FAILURE; logger.atInfo().log(cause.getMessage()); - - //As always, inform the ProbingStep that we successfully completed this action + finished.setSuccess(); + } else if (ServerSideException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + status = ResponseType.ERROR; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (InternalException.class.isInstance(cause)){ + logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - } else { - //On UndeterminedStateException, we know the response type is an error. - - //Since it wasn't a success, we still log what caused the ERROR - logger.atWarning().log(cause.getMessage()); finished.setFailure(cause); - - //As this was an ERROR in performing the action, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } + + //due to failure, close channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } -} \ No newline at end of file +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 1ec4e314813..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,23 +14,20 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -47,50 +44,26 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ - private final Bootstrap bootstrap; - - /** {@link Protocol} for when redirected to http endpoint. */ - private final Protocol httpWhoisProtocol; - - /** {@link Protocol} for when redirected to https endpoint. */ - private final Protocol httpsWhoisProtocol; - - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } + public WebWhoisActionHandler() {} /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; + if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - //On success, we always pass message to ActionHandler's channelRead0 method. + logger.atInfo().log("Response Received: " + response); super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -101,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -111,59 +84,45 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); - } + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) .build(); + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } + logger.atInfo().log("Successfully Closed Connection"); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); + throw new ResponseException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 58c395ad86e..4afc5d95ba7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,52 +1,33 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -/** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} - * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection. - */ -public class WebWhoisMessageHandler extends ChannelDuplexHandler { +public class WebWhoisMessageHandler extends MessageHandler { + + private HttpRequestMessage request; @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - HttpRequestMessage request = (HttpRequestMessage) msg; + request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + FullHttpResponse originalResponse = (FullHttpResponse) msg; - HttpResponseMessage response = new HttpResponseMessage(originalResponse); + InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8fbb55c6339..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,13 +6,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} - * (but needs to implement {@link OutboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion - * from {@link FullHttpRequest} to its type

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -35,6 +14,11 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + + @Override public HttpRequestMessage setUri(String path) { @@ -42,22 +26,16 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - - //creates message based on content found in original request - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - - - //stores headers from request in finalRequest - request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - - return finalRequest; - + HttpRequestMessage output; + if (buf == null) { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + } else { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + } + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 776e7de0824..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,33 +1,11 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} - * (but needs to implement {@link InboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion - * from {@link FullHttpResponse} to its type

- */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -39,20 +17,22 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } - /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); - //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - //stores headers from response in finalResponse - response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); return finalResponse; } + + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index d8a28c25dbd..ba50d0707ec 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,18 +14,9 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; - /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in * channel pipeline */ -public interface OutboundMessageType { - - /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; +public interface OutboundMessageType {} - /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - @Override - String toString(); -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index 817d7245b1f..cbcf2fc82b0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,14 +15,12 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -85,57 +83,57 @@ public class ProbingActionTest { /** Sets up a {@link Protocol} corresponding to when a new connection is created */ private void setupNewChannelProtocol() { protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(false) .build(); } /** Sets up a {@link Protocol} corresponding to when a new connection exists */ private void setupExistingChannelProtocol() { protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(true) + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(true) .build(); } - /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ + /** Sets up a {@link NewChannelAction} with test specified attributes */ private void setupNewChannelAction() { - newChannelAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) + newChannelAction = NewChannelAction.builder() + .bootstrap(bootstrap) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .address(address) .build(); } private void setupChannel() { channel = new EmbeddedChannel(); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ + /** Sets up a {@link ExistingChannelAction} with test specified attributes */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ProbingAction.builder() - .setChannel(channel) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost("") + existingChannelAction = ExistingChannelAction.builder() + .channel(channel) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") .build(); } @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { + public void testBehavior_existingChannel() { //setup setupChannel(); setupExistingChannelProtocol(); + setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); - setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -149,7 +147,6 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -159,9 +156,9 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); setupNewChannelAction(); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index a4474b6b8b5..67e2cb7165d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; import static com.google.common.truth.Truth.assertThat; @@ -34,7 +20,7 @@ import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform */ public abstract class TestServer { private LocalAddress localAddress; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 06b19ea3607..ab9997b6c68 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -34,10 +20,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - *

It will either redirect the client to the correct location if given the + * It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location

+ * an unexpected host location */ public class WebWhoisServer extends TestServer { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 68bdd0bcef0..8d1722c9625 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,15 +17,15 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.Tokens.Token; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpMessage; @@ -37,8 +37,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; -import java.net.SocketAddress; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -143,55 +141,26 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } - - @Override - public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { - message = args[0]; - return this; - } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .build(); + public static class TestStep extends ProbingStep { - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); + public TestStep(Protocol protocol, String testMessage, LocalAddress address) { + super(protocol, new DuplexMessageTest(testMessage)); + this.address = address; + this.duration = Duration.ZERO; + } } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; + public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { + super(protocol, new DuplexMessageTest()); + future = new DefaultPromise(eventLoopGroup.next()) {}; + duration = Duration.ZERO; } @Override @@ -201,16 +170,11 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } - - @Override - public String toString() { - return "Dummy Step"; - } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - protected String host; + private String host; protected TestToken(String host) { this.host = host; @@ -226,7 +190,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String host() { + public String getHost() { return host; } @@ -257,22 +221,6 @@ public Channel channel() { } } - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - - } - /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index 295bb809a13..ef5cba5b60d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,11 +16,12 @@ import static com.google.common.truth.Truth.assertThat; -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,21 +34,21 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); + private static String TEST_DOMAIN = "test"; - public Token webToken = new WebWhoisToken(TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAIN); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 3ecbdcc0d06..518bb9ba686 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,7 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -23,13 +22,12 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 83d004d4555..d8a672758da 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,20 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; -import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; @@ -66,13 +64,7 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of()) - .setName("http") - .setPersistentConnection(false) - .setPort(HTTPS_PORT) - .build(); - + private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; private LocalAddress address; private EmbeddedChannel channel; @@ -80,39 +72,33 @@ public class WebWhoisActionHandlerTest { private ProbingAction probingAction; private Provider actionHandlerProvider; - private String generateLocalAddress(String addressString) { - String modifiedAddress = addressString + System.currentTimeMillis(); - address = new LocalAddress(modifiedAddress); - return modifiedAddress; + private void generateLocalAddress() { + address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); } - /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, boolean persistentConnection) { + private Protocol createProtocol(String name, int port) { return Protocol.builder() - .setName(name) - .setPort(port) - .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) - .setPersistentConnection(persistentConnection) + .name(name) + .port(port) + .handlerProviders(ImmutableList.of(actionHandlerProvider)) + .persistentConnection(false) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { - actionHandler = new WebWhoisActionHandler( - bootstrap, - STANDARD_PROTOCOL, - STANDARD_PROTOCOL, - messageTemplate - ); + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + setupProbingActionBasic( + protocol, + outboundMessage, + makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - setupProbingActionWithChannel(protocol, outboundMessage); + channel.attr(PROBING_ACTION_KEY).set(probingAction); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -121,23 +107,25 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } /**Sets up probingAction for when testing redirection */ - private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setHost(TARGET_HOST) - .setChannel(channel) + private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(TARGET_HOST) + .address(DEFAULT_ADDRESS) .build(); } - private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(addressString) + private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(host) + .address(address) .build(); } @@ -148,21 +136,22 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, true); - + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); setupChannel(initialProtocol, msg); + //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -170,28 +159,30 @@ public void testBasic_responseOk() throws Exception { channel.writeInbound(response); - //assesses that we successfully receivved good response and protocol is unchanged + //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testBasic_responseFailure_badRequest() { + public void testBasic_responseFailure() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseBad", 0, true); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseBad", 0); + generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = HttpResponseMessage + .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -200,18 +191,18 @@ public void testBasic_responseFailure_badRequest() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException).isTrue(); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testBasic_responseFailure_badURL() { + public void testBasic_responseError() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseError", 0, true); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseError", 0); + generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -222,7 +213,7 @@ public void testBasic_responseFailure_badURL() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -231,31 +222,29 @@ public void testBasic_responseFailure_badURL() { //assesses that listener is triggered, and event is success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test public void testBasic_redirectCloseChannel() { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", 0, true); - setupChannel(initialProtocol, msg); + HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", 0); + generateLocalAddress(); + setupChannel(initialProtocol, outboundMessage); //stores future ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); + channel.writeOutbound(outboundMessage); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -269,15 +258,44 @@ public void testBasic_redirectCloseChannel() { } @Test - public void testAdvanced_responseOk() throws UndeterminedStateException { + public void testBasic_redirectHost() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + + + //store future + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); + + + channel.writeInbound(originalResponse); + + ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + + //gets changed protocol + Protocol newProtocol = newAction.protocol(); + + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); + assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); + } + + @Test + public void testAdvanced_responseOk() { //setup EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", TARGET_HOST, group); //stores future ChannelFuture future = probingAction.call(); @@ -287,21 +305,21 @@ public void testAdvanced_responseOk() throws UndeterminedStateException { } @Test - public void testAdvanced_responseFailure() throws UndeterminedStateException { + public void testAdvanced_responseFailure() { //setup EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", TARGET_HOST, group); //stores future ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged - assertThrows(FailureException.class, future::syncUninterruptibly); + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } } From 06810307f32bce1348b4e6db3e880d7b42c3f5c8 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 228/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 +++++++++----- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/ProbingSequence.java | 1 - .../monitoring/blackbox/ProbingStep.java | 7 +--- .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 - .../monitoring/blackbox/Tokens/Token.java | 4 +- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../monitoring/blackbox/WebWhoisModule.java | 2 +- .../exceptions/EppClientException.java | 29 ------------- .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++- .../handlers/WebWhoisMessageHandler.java | 22 +++++++++- .../blackbox/messages/HttpRequestMessage.java | 41 +++++++++++++------ .../messages/HttpResponseMessage.java | 26 ++++++++---- .../messages/OutboundMessageType.java | 1 - .../blackbox/TestServers/TestServer.java | 16 +++++++- .../blackbox/TestServers/WebWhoisServer.java | 18 +++++++- 19 files changed, 145 insertions(+), 85 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6387207fea4..2eb90a1d6c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -119,4 +119,3 @@ public String toString() { } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 5bad5abf6bf..80b04a3d0c9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.exceptions.EppClientException; import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; import io.netty.channel.local.LocalAddress; -import java.io.IOException; + import java.util.function.Consumer; import org.joda.time.Duration; @@ -164,7 +162,4 @@ public String toString() { message(), parent); } - } - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 71a2777cf5f..624f08fd4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -69,4 +69,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dba905c0e49..7200a1877e2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -197,4 +197,4 @@ static SslClientInitializer provideSslClientInitializer(SslPro } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 4afc5d95ba7..0acf223eb9e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; @@ -8,6 +22,11 @@ import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; +/** + * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} + * in case of reuse for redirection + */ public class WebWhoisMessageHandler extends MessageHandler { private HttpRequestMessage request; @@ -15,6 +34,7 @@ public class WebWhoisMessageHandler extends MessageHandler { @Inject public WebWhoisMessageHandler() {} + /** Retains {@link HttpRequestMessage} and calls super write method*/ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { request = (HttpRequestMessage) msg; @@ -23,9 +43,9 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) } + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - FullHttpResponse originalResponse = (FullHttpResponse) msg; InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..b06938d80a1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +31,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,16 +38,19 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + + request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + + return finalRequest; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..283b14440ac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,7 +33,7 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); @@ -26,13 +43,8 @@ public static HttpResponseMessage fromResponse(FullHttpResponse response) { else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); return finalResponse; } - - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index ba50d0707ec..e393e47ff46 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -19,4 +19,3 @@ * channel pipeline */ public interface OutboundMessageType {} - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 67e2cb7165d..a4474b6b8b5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static com.google.common.truth.Truth.assertThat; @@ -20,7 +34,7 @@ import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { private LocalAddress localAddress; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index ab9997b6c68..06b19ea3607 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -20,10 +34,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - * It will either redirect the client to the correct location if given the + *

It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location + * an unexpected host location

*/ public class WebWhoisServer extends TestServer { From ffcb444416271dd3b9398f2e307c5080a9b3fdce Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 229/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 --- .../monitoring/blackbox/NewChannelAction.java | 144 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProberModule.java | 80 ++--- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingSequence.java | 130 ++++----- .../monitoring/blackbox/ProbingStep.java | 147 +++++----- .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/Protocol.java | 3 +- .../monitoring/blackbox/TokenModule.java | 35 --- .../monitoring/blackbox/Tokens/Token.java | 47 --- .../blackbox/Tokens/WebWhoisToken.java | 54 ---- .../monitoring/blackbox/WebWhoisModule.java | 169 ++++++----- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/ActionHandler.java | 102 +++++-- .../blackbox/handlers/MessageHandler.java | 24 -- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../handlers/WebWhoisMessageHandler.java | 17 +- .../blackbox/messages/HttpRequestMessage.java | 46 ++- .../messages/HttpResponseMessage.java | 14 +- .../messages/OutboundMessageType.java | 11 +- .../monitoring/blackbox/tokens/Token.java | 20 +- .../blackbox/tokens/WebWhoisToken.java | 32 +- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 31 files changed, 687 insertions(+), 920 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 73bd9127852..0daaf16ded4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,99 +14,59 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; import javax.inject.Singleton; +import org.joda.time.Duration; /** - * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} - * - *

Provides

+ * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores + * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. */ @Module public class ProberModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; + /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + private static final Duration DEFAULT_DURATION = new Duration(4000L); + + /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides - @HttpWhoisProtocol - ProbingSequence provideHttpWhoisSequence( - @HttpWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpsWhoisProtocol - ProbingSequence provideHttpsWhoisSequence( - @HttpsWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return httpWhoIsPort; - } - - @Provides - @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return httpsWhoIsPort; + @Singleton + Duration provideDuration() { + return DEFAULT_DURATION; } + /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - ImmutableMap providePortToProtocolMap( - Set protocolSet) { - return Maps.uniqueIndex(protocolSet, Protocol::port); + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - - + /** Root level {@link Component} that provides each {@link ProbingSequence}. */ @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, - TokenModule.class }) public interface ProberComponent { - @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); - - @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); - - ImmutableMap providePortToProtocolMap(); - - @WebWhoisProtocol Token provideWebWhoisToken(); + //Standard WebWhois sequence + @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2eb90a1d6c3..2dbf48256f9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,108 +14,100 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} - * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ - private EventLoopGroup eventGroup; + /**Each {@link ProbingSequence} requires a start token to begin running. */ + private Token startToken; - /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ - private Bootstrap bootstrap; - - public Bootstrap getBootstrap() { - return bootstrap; - } - - public void start(Token token) { - // calls the first step with input token; - firstStep.accept(token); + public void start() { + // calls the first step with startToken; + firstStep.accept(startToken); } /** - * {@link Builder} which takes in {@link ProbingStep}s - * - * @param Same specified {@code C} for overall {@link ProbingSequence} + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. */ - public static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstSequenceStep; - private EventLoopGroup eventLoopGroup; - private Class classType; - - Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public static class Builder { + + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstRepeatedStep; + private Bootstrap bootstrap; + private Token startToken; + + /** + * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. + * + *

Must be called before adding {@link ProbingStep.Builder}s.

+ */ + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } + + /** Adds start token that activate {@link ProbingSequence}. */ + public Builder addToken(Token token) { + startToken = token; return this; } - Builder addStep(ProbingStep step) { - if (currentStep == null) { + /** + * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * built, and pointed to by the previous {@link ProbingStep} added. + */ + public Builder addStep(ProbingStep.Builder stepBuilder) { + assert (bootstrap != null); + ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + + if (currentStep == null) firstStep = step; - } else { + else currentStep.nextStep(step); - } + currentStep = step; return this; } - /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ - Builder makeFirstRepeated() { - firstSequenceStep = currentStep; - return this; - } - /** Set the class to be the same as {@code C} */ - public Builder setClass(Class classType) { - this.classType = classType; + /** We take special note of the first repeated step. */ + public Builder markFirstRepeated() { + firstRepeatedStep = currentStep; return this; } - public ProbingSequence build() { - currentStep.nextStep(firstSequenceStep); + /** + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and + * calls private constructor to create {@link ProbingSequence}. + */ + public ProbingSequence build() { + if (firstRepeatedStep == null) + firstRepeatedStep = firstStep; + + currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); - return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + return new ProbingSequence(this.firstStep, this.startToken); } - } - /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ - private void setParents() { - ProbingStep currentStep = firstStep.parent(this).nextStep(); - - while (currentStep != firstStep) { - currentStep = currentStep.parent(this).nextStep(); - } - } - private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, - Class classType) { + private ProbingSequence(ProbingStep firstStep, Token startToken) { this.firstStep = firstStep; - this.eventGroup = eventLoopGroup; - this.bootstrap = new Bootstrap() - .group(eventGroup) - .channel(classType); - setParents(); - } - - @Override - public String toString() { - return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); - + this.startToken = startToken; } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 80b04a3d0c9..d54acef325a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,152 +14,145 @@ package google.registry.monitoring.blackbox; +import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.local.LocalAddress; - import java.util.function.Consumer; import org.joda.time.Duration; /** - * Represents generator of actions performed at each step in {@link ProbingSequence} - * - * @param See {@code C} in {@link ProbingSequence} + * {@link AutoValue} class that represents generator of actions performed at each step + * in {@link ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies - * these components on each loop iteration with the consumed {@link Token} and from that, - * generates new {@link ProbingAction} to perform<./p> + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. + * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, + * generates a new {@link ProbingAction} to call.

* - *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -public abstract class ProbingStep implements Consumer { +@AutoValue +public abstract class ProbingStep implements Consumer { - public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); - protected static final Duration DEFAULT_DURATION = new Duration(2000L); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - protected LocalAddress address = DEFAULT_ADDRESS; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ private boolean isLastStep = false; - private ProbingStep nextStep; - private ProbingSequence parent; + private ProbingStep nextStep; - protected Duration duration; + abstract Duration duration(); + abstract Protocol protocol(); + abstract OutboundMessageType messageTemplate(); + abstract Bootstrap bootstrap(); - protected final Protocol protocol; - protected final OutboundMessageType message; - protected ProbingStep(Protocol protocol, OutboundMessageType message) { - this.protocol = protocol; - this.message = message; - } + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder setDuration(Duration value); - private OutboundMessageType message() { - return message; - } + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); - Protocol protocol() { - return protocol; + public abstract ProbingStep build(); } + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - ProbingStep parent(ProbingSequence parent) { - this.parent = parent; - return this; - } - - /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ private ProbingAction generateAction(Token token) throws InternalException { - ProbingAction generatedAction; - - OutboundMessageType message = token.modifyMessage(message()); - - //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction - if (protocol().persistentConnection() && token.channel() != null) { - generatedAction = ExistingChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .channel(token.channel()) - .build(); - } else { - generatedAction = NewChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .bootstrap(parent.getBootstrap()) - .address(address) - .build(); - - } - return generatedAction; + OutboundMessageType message = token.modifyMessage(messageTemplate()); + ProbingAction.Builder probingActionBuilder = ProbingAction.builder() + .setDelay(duration()) + .setProtocol(protocol()) + .setOutboundMessage(message) + .setHost(token.getHost()) + .setBootstrap(bootstrap()); + + if (token.channel() != null) + probingActionBuilder.setChannel(token.channel()); + + return probingActionBuilder.build(); } - /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } @Override public void accept(Token token) { - ProbingAction nextAction; + ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - nextAction = generateAction(token); + currentAction = generateAction(token); } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - //If the next step maintains the connection, pass on the channel from this - if (protocol().persistentConnection()) { - token.channel(nextAction.channel()); - } + //call the created action - ChannelFuture future = nextAction.call(); + ChannelFuture future; + + try { + future = currentAction.call(); + + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Performed"); + nextStep.accept(generateNextToken(token)); + return; + } + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - nextStep.accept(generateNextToken(token)); + //If the next step maintains the connection, pass on the channel from this } else { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + token.setChannel(currentAction.channel()); + + nextStep.accept(generateNextToken(token)); + + }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n" + - "and parent sequence: %s", + "OutboundMessage: %s\n", protocol(), - message(), - parent); + messageTemplate().getClass().getName()); } + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 624f08fd4e9..b0342c74b7d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -29,7 +29,7 @@ public abstract class Protocol { /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - public abstract String name(); + abstract String name(); public abstract int port(); @@ -43,7 +43,6 @@ public static Builder builder() { return new AutoValue_Protocol.Builder(); } - /** Builder for {@link Protocol}. */ @AutoValue.Builder public abstract static class Builder { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 7200a1877e2..dcc9635beaa 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,62 +17,86 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; -import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandler; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - final static String DOMAIN_SUFFIX = "whois.nic."; + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + private static final String DOMAIN_PREFIX = "whois.nic."; + + /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + private static final int maximumMessageLengthBytes = 512 * 1024; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - - - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - - + /** {@link Provides} standard WebWhois sequence. */ @Provides - @HttpWhoisProtocol - static ProbingStep provideHttpWhoisProbingSequence( - @HttpWhoisProtocol Protocol httpWhoisProtocol) { - return new ProbingStepWeb<>(httpWhoisProtocol); + @WebWhoisProtocol + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, + WebWhoisToken webWhoisToken, + @WebWhoisProtocol Bootstrap bootstrap) { + + return new ProbingSequence.Builder() + .addToken(webWhoisToken) + .setBootstrap(bootstrap) + .addStep(probingStepBuilder) + .build(); } + + /** {@link Provides} only step used in WebWhois sequence. */ @Provides - @HttpsWhoisProtocol - static ProbingStep provideHttpsWhoisProbingStep( - @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { - return new ProbingStepWeb<>(httpsWhoisProtocol); + @WebWhoisProtocol + static ProbingStep.Builder provideWebWhoisStepBuilder( + @HttpWhoisProtocol Protocol httpWhoisProtocol, + HttpRequestMessage messageTemplate, + Duration duration) { + + return ProbingStep.builder() + .setProtocol(httpWhoisProtocol) + .setMessageTemplate(messageTemplate) + .setDuration(duration); } - + /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides @HttpWhoisProtocol @@ -80,28 +104,14 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpProtocolForSet( - @HttpWhoisProtocol int httpWhoisPort, - @HttpWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTP_PROTOCOL_NAME) + .setPort(httpWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } - + /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ @Singleton @Provides @HttpsWhoisProtocol @@ -109,40 +119,28 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpsProtocolForSet( - @HttpsWhoisProtocol int httpsWhoisPort, - @HttpsWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTPS_PROTOCOL_NAME) + .setPort(httpsWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } + /** {@link Provides} the prefix where we probe: "prefix.tld". */ @Provides - @WebWhoisProtocol - String provideHttpWhoisHost() { - return "app"; + @Named("Web-WHOIS-Prefix") + String provideWhoisPrefix() { + return DOMAIN_PREFIX; } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -151,13 +149,14 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -167,33 +166,57 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } + @Provides + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); + } + + @Provides + static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { + return new HttpObjectAggregator(maxContentLength); + } + + /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + @Provides + @HttpsWhoisProtocol + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); + } + /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + @Singleton @Provides @WebWhoisProtocol - static MessageHandler provideMessageHandler() { - return new WebWhoisMessageHandler(); + static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + return new Bootstrap() + .group(eventLoopGroup) + .channel(NioSocketChannel.class); } @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); + @WebWhoisProtocol + int provideMaximumMessageLengthBytes() { + return maximumMessageLengthBytes; } + /** {@link Provides} the list of top level domains to be probed */ + @Singleton @Provides - static HttpObjectAggregator provideHttpObjectAggregator() { - return new HttpObjectAggregator(1048576); + @WebWhoisProtocol + ImmutableList provideTopLevelDomains() { + return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); } @Provides - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index adb833ec629..be3d725c833 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,10 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when - * the action performed failed due to an issue in the connection with the server. + * Base exception class for all instances when the status of the action performed is ERROR. */ -public class ConnectionException extends UndeterminedStateException { +public class ConnectionException extends Exception { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 7898203e92d..e397393b4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,10 +14,11 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; @@ -26,16 +27,18 @@ import io.netty.channel.ChannelPromise; /** - *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} - * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception - * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses - * specify further work to be done for specific kinds of channel pipelines.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed + * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} + * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * + *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -47,28 +50,42 @@ public enum ResponseType {SUCCESS, FAILURE, ERROR} /** Status of response for current {@link ActionHandler} instance */ private static ResponseType status; + /** {@link ChannelPromise} that informs {@link google.registry.monitoring.blackbox.ProbingAction} if response has been received. */ protected ChannelPromise finished; - /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** Returns initialized {@link ChannelPromise} to {@link google.registry.monitoring.blackbox.ProbingAction}.*/ public ChannelFuture getFuture() { return finished; } - /** Initializes new {@link ChannelPromise} */ + /** Initializes the same {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } + /** Initializes the same {@link ChannelPromise} in case current channel is reused (usually for EPP).*/ + public void resetFuture() { + finished = finished.channel().newPromise(); + } + + /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { - //simply marks finished as success + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { + status = ResponseType.SUCCESS; - finished.setSuccess(); + + if (!finished.isSuccess()) { + finished.setSuccess(); + } } - /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ + /** + * Logs the channel and pipeline that caused error, closes channel, then informs + * {@link google.registry.monitoring.blackbox.ProbingAction} listeners of error. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).log(String.format( @@ -76,27 +93,62 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.channel().toString(), ctx.channel().pipeline().toString())); - - if (ResponseException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + if (cause instanceof ResponseException) { + //On ResponseException, we know the response is a failure. As a result, + //we set the status to FAILURE, then inform the MetricsHandler of this status = ResponseType.FAILURE; + + //Since it wasn't a success, we still want to log to see what caused the FAILURE logger.atInfo().log(cause.getMessage()); + + //As always, inform the ProbingStep that we successfully completed this action finished.setSuccess(); - } else if (ServerSideException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + + } else if (cause instanceof ConnectionException) { + //On ConnectionException, we know the response type is an error. As a result, + //we set the status to ERROR, then inform the MetricsHandler of this status = ResponseType.ERROR; + + //Since it wasn't a success, we still log what caused the ERROR logger.atInfo().log(cause.getMessage()); finished.setSuccess(); - } else if (InternalException.class.isInstance(cause)){ + + //As this was an ERROR in the connection, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + } else if (cause instanceof InternalException){ + //For an internal error, metrics should not be collected, so we log what caused this, and + //inform the ProbingStep the Prober had an internal error on this action logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); + + + //As this was an internal error, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } else { - finished.setFailure(cause); + //In the case of any other kind of error, we assume it is some type of connection ERROR, + //so we treat it as such: + + status = ResponseType.ERROR; + + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - //due to failure, close channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + + } + + /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ + @VisibleForTesting + ResponseType getStatus() { + return status; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 0acf223eb9e..58c395ad86e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -17,37 +17,36 @@ import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; /** - * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection + * in case of reuse for redirection. */ -public class WebWhoisMessageHandler extends MessageHandler { - - private HttpRequestMessage request; +public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method*/ + /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - request = (HttpRequestMessage) msg; + HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; - InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); + HttpResponseMessage response = new HttpResponseMessage(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b06938d80a1..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,19 +19,30 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); @@ -39,18 +50,29 @@ public HttpRequestMessage setUri(String path) { } /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; - ByteBuf buf = request.content(); + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; - request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + } else { + throw new IllegalArgumentException(); + } + } - return finalRequest; + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 283b14440ac..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -34,17 +34,9 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index e393e47ff46..c7ba8454ecd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,8 +14,17 @@ package google.registry.monitoring.blackbox.messages; +import google.registry.monitoring.blackbox.exceptions.InternalException; + /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in * channel pipeline */ -public interface OutboundMessageType {} +public interface OutboundMessageType { + + /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + public OutboundMessageType modifyMessage(String... args) throws InternalException; + + /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + public String name(); +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dab5851e8d8..dd1882b5686 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,18 +14,16 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.ProbingSequence; -import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} - * in a single loop of a {@link ProbingSequence}. + * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} + * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes + * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -33,21 +31,17 @@ */ public abstract class Token { - /** - * {@link Channel} that always starts out as null. Once a persistent connection - * is made (such as EPP), that channel is stored in the token and passed on to - * later steps in the sequence until a new loop begins. - */ + /** {@link Channel} that always starts out as null. */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String host(); + public abstract String getHost(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index bb06ee89db6..2847e5ce0eb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; -import java.util.LinkedList; +import java.util.List; import javax.inject.Inject; import javax.inject.Named; @@ -33,38 +33,42 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final static String PREFIX = "whois.nic."; + private final String prefix; /** {@link ImmutableList} of all top level domains to be probed. */ - private final Iterator topLevelDomainsIterator; + private final ImmutableList topLevelDomains; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private String currentDomain; + private int domainsIndex; @Inject - public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken( + @Named("Web-WHOIS-Prefix") String prefix, + @WebWhoisProtocol ImmutableList topLevelDomains) { - topLevelDomainsIterator = topLevelDomains.iterator(); - currentDomain = topLevelDomainsIterator.next(); + domainsIndex = 0; + this.prefix = prefix; + this.topLevelDomains = topLevelDomains; } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + domainsIndex += 1; + domainsIndex %= topLevelDomains.size(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { - return original.modifyMessage(host()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { + return original.modifyMessage(getHost()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String host() { - return PREFIX + currentDomain; + public String getHost() { + return prefix + topLevelDomains.get(domainsIndex); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Mon, 29 Jul 2019 12:04:58 -0400 Subject: [PATCH 230/337] Minor Style Fixes --- .../monitoring/blackbox/ProbingAction.java | 85 ++++++++++--------- .../monitoring/blackbox/ProbingStep.java | 8 +- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..3f6a962b12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -89,11 +90,47 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** The {@link SocketAddress} instance that specifies remote address of connection */ + @Nullable public abstract SocketAddress address(); /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ public abstract Optional bootstrap(); + + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> actionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** * The method that performs the work of the actual action. * @@ -130,41 +167,13 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } @@ -224,7 +233,7 @@ public abstract static class Builder { abstract Channel channel(); - abstract Optional address(); + abstract SocketAddress address(); abstract Optional bootstrap(); @@ -233,7 +242,7 @@ public abstract static class Builder { abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) + if (address() == null) //If no address has been supplied, we set it based on the host and port setAddress(new InetSocketAddress(host(), protocol().port())); @@ -259,7 +268,7 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap().get().connect(address()); setChannel(connectionFuture.channel()); setConnectionFuture(connectionFuture); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index d54acef325a..47c89c72c11 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -21,7 +21,9 @@ import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import java.net.SocketAddress; import java.util.function.Consumer; +import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -48,6 +50,7 @@ public abstract class ProbingStep implements Consumer { abstract Protocol protocol(); abstract OutboundMessageType messageTemplate(); abstract Bootstrap bootstrap(); + @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -60,6 +63,8 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); + public abstract Builder setAddress(SocketAddress address); + public abstract ProbingStep build(); } @@ -87,7 +92,8 @@ private ProbingAction generateAction(Token token) throws InternalException { .setProtocol(protocol()) .setOutboundMessage(message) .setHost(token.getHost()) - .setBootstrap(bootstrap()); + .setBootstrap(bootstrap()) + .setAddress(address()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); From 1b2bdca976039b8e9cc6e5d727c278f562a2df15 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 231/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From c6994feebf5396decf6f648a8c6e5da702405bb7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 232/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- .../registry/monitoring/blackbox/Prober.java | 9 +- .../monitoring/blackbox/ProberModule.java | 15 +- .../monitoring/blackbox/ProbingAction.java | 96 ++++----- .../monitoring/blackbox/ProbingSequence.java | 24 +-- .../monitoring/blackbox/ProbingStep.java | 55 +++-- .../monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 49 ++--- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 30 --- .../exceptions/ResponseException.java | 29 --- .../blackbox/handlers/ActionHandler.java | 94 ++------ .../handlers/WebWhoisActionHandler.java | 51 ++--- .../blackbox/messages/HttpRequestMessage.java | 4 +- .../messages/HttpResponseMessage.java | 6 +- .../messages/OutboundMessageType.java | 7 +- .../monitoring/blackbox/tokens/Token.java | 20 +- .../blackbox/tokens/WebWhoisToken.java | 32 ++- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../blackbox/ProbingActionTest.java | 57 ++--- .../monitoring/blackbox/TestUtils.java | 84 ++++++-- .../monitoring/blackbox/TokenTest.java | 19 +- .../blackbox/handlers/TestActionHandler.java | 8 +- .../handlers/WebWhoisActionHandlerTest.java | 201 ++++++++---------- 27 files changed, 411 insertions(+), 490 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..307afd34d81 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +29,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 0daaf16ded4..1db97d1b581 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,14 +14,18 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.Set; import javax.inject.Singleton; import org.joda.time.Duration; @@ -33,7 +37,7 @@ public class ProberModule { /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = new Duration(4000L); + private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @@ -42,6 +46,12 @@ EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + @Provides + @Singleton + Class provideChannelClass() { + return NioSocketChannel.class; + } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides @Singleton @@ -51,6 +61,7 @@ Duration provideDuration() { /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides + @Singleton static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; @@ -66,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); + Set provideAllSequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 3f6a962b12d..67494dd5f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,25 +14,29 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -65,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -80,31 +87,18 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - @Nullable - public abstract SocketAddress address(); - - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { // Write appropriate outboundMessage to pipeline ChannelFuture channelFuture = actionHandler.getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> actionHandler.resetFuture(), - //inform ProbingStep of the status of our action future -> { if (future.isSuccess()) @@ -141,7 +135,7 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -154,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -180,19 +174,24 @@ public ChannelFuture performAction() throws InternalException { /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -210,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -221,40 +226,30 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract SocketAddress address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (address() == null) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + System.out.println("test"); + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -268,14 +263,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -293,7 +285,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2dbf48256f9..91c4165c068 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -49,32 +49,18 @@ public static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; private ProbingStep firstRepeatedStep; - private Bootstrap bootstrap; - private Token startToken; - /** - * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. - * - *

Must be called before adding {@link ProbingStep.Builder}s.

- */ - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } + private Token startToken; - /** Adds start token that activate {@link ProbingSequence}. */ - public Builder addToken(Token token) { - startToken = token; - return this; + public Builder(Token startToken) { + this.startToken = startToken; } /** - * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, * built, and pointed to by the previous {@link ProbingStep} added. */ - public Builder addStep(ProbingStep.Builder stepBuilder) { - assert (bootstrap != null); - ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + public Builder addStep(ProbingStep step) { if (currentStep == null) firstStep = step; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 47c89c72c11..ca980100067 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import java.net.SocketAddress; import java.util.function.Consumer; -import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -39,18 +37,23 @@ @AutoValue public abstract class ProbingStep implements Consumer { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ - private boolean isLastStep = false; + protected boolean isLastStep = false; private ProbingStep nextStep; + /** Time delay duration between actions. */ abstract Duration duration(); + + /** {@link Protocol} type for this step. */ abstract Protocol protocol(); + + /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ abstract OutboundMessageType messageTemplate(); + + /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ abstract Bootstrap bootstrap(); - @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -63,8 +66,6 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); - public abstract Builder setAddress(SocketAddress address); - public abstract ProbingStep build(); } @@ -85,18 +86,18 @@ ProbingStep nextStep() { } /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws InternalException { + private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) .setProtocol(protocol()) .setOutboundMessage(message) - .setHost(token.getHost()) - .setBootstrap(bootstrap()) - .setAddress(address()); + .setHost(token.host()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); + else + probingActionBuilder.setBootstrap(bootstrap()); return probingActionBuilder.build(); } @@ -107,44 +108,58 @@ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } + /** + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. + * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

+ */ @Override public void accept(Token token) { ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - //call the created action ChannelFuture future; - try { + //call the generated action future = currentAction.call(); - - } catch(InternalException e) { + } catch(UndeterminedStateException e) { + //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); + + //Move on to next step in ProbingSequence nextStep.accept(generateNextToken(token)); return; } - //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - //If the next step maintains the connection, pass on the channel from this + } else { + //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index b0342c74b7d..92470ef62c8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -29,7 +29,7 @@ public abstract class Protocol { /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - abstract String name(); + public abstract String name(); public abstract int port(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dcc9635beaa..c5e41fea38b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,6 +18,7 @@ import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,6 +27,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; @@ -44,11 +46,10 @@ @Module public class WebWhoisModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - private static final String DOMAIN_PREFIX = "whois.nic."; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; + private static final String HTTP_PROTOCOL_NAME = "http"; + private static final String HTTPS_PROTOCOL_NAME = "https"; /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; @@ -68,16 +69,14 @@ public class WebWhoisModule { /** {@link Provides} standard WebWhois sequence. */ @Provides - @WebWhoisProtocol + @Singleton + @IntoSet ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, - WebWhoisToken webWhoisToken, - @WebWhoisProtocol Bootstrap bootstrap) { + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { - return new ProbingSequence.Builder() - .addToken(webWhoisToken) - .setBootstrap(bootstrap) - .addStep(probingStepBuilder) + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) .build(); } @@ -85,15 +84,18 @@ ProbingSequence provideWebWhoisSequence( /** {@link Provides} only step used in WebWhois sequence. */ @Provides @WebWhoisProtocol - static ProbingStep.Builder provideWebWhoisStepBuilder( + static ProbingStep provideWebWhoisStep( @HttpWhoisProtocol Protocol httpWhoisProtocol, + @WebWhoisProtocol Bootstrap bootstrap, HttpRequestMessage messageTemplate, Duration duration) { return ProbingStep.builder() .setProtocol(httpWhoisProtocol) + .setBootstrap(bootstrap) .setMessageTemplate(messageTemplate) - .setDuration(duration); + .setDuration(duration) + .build(); } /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @@ -126,13 +128,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** {@link Provides} the prefix where we probe: "prefix.tld". */ - @Provides - @Named("Web-WHOIS-Prefix") - String provideWhoisPrefix() { - return DOMAIN_PREFIX; - } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @@ -187,10 +182,12 @@ static SslClientInitializer provideSslClientInitializer(SslPro @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + static Bootstrap provideBootstrap( + EventLoopGroup eventLoopGroup, + Class channelClass){ return new Bootstrap() .group(eventLoopGroup) - .channel(NioSocketChannel.class); + .channel(channelClass); } @Provides @@ -210,13 +207,13 @@ ImmutableList provideTopLevelDomains() { @Provides @HttpWhoisProtocol int provideHttpWhoisPort() { - return httpWhoIsPort; + return HTTP_WHOIS_PORT; } @Provides @HttpsWhoisProtocol int provideHttpsWhoisPort() { - return httpsWhoIsPort; + return HTTPS_WHOIS_PORT; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index be3d725c833..adb833ec629 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,9 +15,10 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is ERROR. + * Subclass of {@link UndeterminedStateException} that represents all instances when + * the action performed failed due to an issue in the connection with the server. */ -public class ConnectionException extends Exception { +public class ConnectionException extends UndeterminedStateException { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index e397393b4e9..0c9e93cc6dd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,13 +14,11 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -33,7 +31,7 @@ * messages that implement the {@link InboundMessageType} interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

@@ -44,111 +42,59 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); - - } else if (cause instanceof InternalException){ - //For an internal error, metrics should not be collected, so we log what caused this, and - //inform the ProbingStep the Prober had an internal error on this action - logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - - //As this was an internal error, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } else { - //In the case of any other kind of error, we assume it is some type of connection ERROR, - //so we treat it as such: + //On UndeterminedStateException, we know the response type is an error. - status = ResponseType.ERROR; - - logger.atInfo().log(cause.getMessage()); - finished.setSuccess(); + //Since it wasn't a success, we still log what caused the ERROR + logger.atWarning().log(cause.getMessage()); + finished.setFailure(cause); + //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } - - /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ - @VisibleForTesting - ResponseType getStatus() { - return status; - } -} - +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 69d5b7f1603..1ec4e314813 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -22,13 +22,12 @@ import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -62,27 +61,17 @@ public class WebWhoisActionHandler extends ActionHandler { /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ private final HttpRequestMessage requestMessage; - /** Default port for http. */ - private int httpPort; - - /** default port for https. */ - private int httpsPort; - @Inject public WebWhoisActionHandler( @WebWhoisProtocol Bootstrap bootstrap, @HttpWhoisProtocol Protocol httpWhoisProtocol, @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage, - @HttpWhoisProtocol int httpPort, - @HttpsWhoisProtocol int httpsPort) { + HttpRequestMessage requestMessage) { this.bootstrap = bootstrap; this.httpWhoisProtocol = httpWhoisProtocol; this.httpsWhoisProtocol = httpsWhoisProtocol; this.requestMessage = requestMessage; - this.httpPort = httpPort; - this.httpsPort = httpsPort; } @@ -93,7 +82,7 @@ public WebWhoisActionHandler( */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -112,7 +101,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -123,12 +112,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; - if (newPort == httpPort) { + if (url.getProtocol().equals(httpWhoisProtocol.name())) { newProtocol = httpWhoisProtocol; - } else if (newPort == httpsPort) { + } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -143,34 +132,38 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) .setHost(newHost) .build(); - //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); - //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..b4c01d06a8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,12 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..f1b2d6ac6a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -25,11 +25,7 @@ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { - super(version, status); - } - - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index c7ba8454ecd..d8a28c25dbd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,7 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in @@ -23,8 +23,9 @@ public interface OutboundMessageType { /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - public OutboundMessageType modifyMessage(String... args) throws InternalException; + OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - public String name(); + @Override + String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dd1882b5686..dab5851e8d8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,16 +14,18 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.ProbingSequence; +import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} - * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} + * in a single loop of a {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * in a {@link ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -31,17 +33,21 @@ */ public abstract class Token { - /** {@link Channel} that always starts out as null. */ + /** + * {@link Channel} that always starts out as null. Once a persistent connection + * is made (such as EPP), that channel is stored in the token and passed on to + * later steps in the sequence until a new loop begins. + */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String getHost(); + public abstract String host(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 2847e5ce0eb..bb06ee89db6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import javax.inject.Inject; import javax.inject.Named; @@ -33,42 +33,38 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final String prefix; + private final static String PREFIX = "whois.nic."; /** {@link ImmutableList} of all top level domains to be probed. */ - private final ImmutableList topLevelDomains; + private final Iterator topLevelDomainsIterator; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private int domainsIndex; + private String currentDomain; @Inject - public WebWhoisToken( - @Named("Web-WHOIS-Prefix") String prefix, - @WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { - domainsIndex = 0; - this.prefix = prefix; - this.topLevelDomains = topLevelDomains; + topLevelDomainsIterator = topLevelDomains.iterator(); + currentDomain = topLevelDomainsIterator.next(); } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - domainsIndex += 1; - domainsIndex %= topLevelDomains.size(); + currentDomain = topLevelDomainsIterator.next(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { - return original.modifyMessage(getHost()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + return original.modifyMessage(host()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String getHost() { - return prefix + topLevelDomains.get(domainsIndex); + public String host() { + return PREFIX + currentDomain; } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v(builder() - .bootstrap(bootstrap) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") - .address(address) + newChannelAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) .build(); } private void setupChannel() { channel = new EmbeddedChannel(); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ExistingChannelAction.builder() - .channel(channel) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") + existingChannelAction = ProbingAction.builder() + .setChannel(channel) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") .build(); } @Test - public void testBehavior_existingChannel() { + public void testBehavior_existingChannel() throws UndeterminedStateException { //setup setupChannel(); setupExistingChannelProtocol(); - setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); + setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -147,6 +149,7 @@ public void testBehavior_existingChannel() { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -156,9 +159,9 @@ public void testBehavior_existingChannel() { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - setupNewChannelAction(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + setupNewChannelAction(); ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 8d1722c9625..68bdd0bcef0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,15 +17,15 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpMessage; @@ -37,6 +37,8 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; +import java.net.SocketAddress; +import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -141,26 +143,55 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } + + @Override + public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { + message = args[0]; + return this; + } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static class TestStep extends ProbingStep { + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .build(); - public TestStep(Protocol protocol, String testMessage, LocalAddress address) { - super(protocol, new DuplexMessageTest(testMessage)); - this.address = address; - this.duration = Duration.ZERO; - } + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { - super(protocol, new DuplexMessageTest()); - future = new DefaultPromise(eventLoopGroup.next()) {}; - duration = Duration.ZERO; + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; } @Override @@ -170,11 +201,16 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } + + @Override + public String toString() { + return "Dummy Step"; + } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - private String host; + protected String host; protected TestToken(String host) { this.host = host; @@ -190,7 +226,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String getHost() { + public String host() { return host; } @@ -221,6 +257,22 @@ public Channel channel() { } } + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..295bb809a13 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,12 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -34,21 +33,21 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); - } catch(InternalException e) { + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 518bb9ba686..3ecbdcc0d06 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,7 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws FailureException, UndeterminedStateException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index d8a672758da..2483bd65b1f 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,18 +15,20 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; @@ -64,7 +66,13 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private static final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of()) + .setName("http") + .setPersistentConnection(false) + .setPort(HTTPS_PORT) + .build(); + private LocalAddress address; private EmbeddedChannel channel; @@ -72,33 +80,39 @@ public class WebWhoisActionHandlerTest { private ProbingAction probingAction; private Provider actionHandlerProvider; - private void generateLocalAddress() { - address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + private String generateLocalAddress(String addressString) { + String modifiedAddress = addressString + System.currentTimeMillis(); + address = new LocalAddress(modifiedAddress); + return modifiedAddress; } + /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port) { + private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of(actionHandlerProvider)) - .persistentConnection(false) + .setName(name) + .setPort(port) + .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) + .setPersistentConnection(persistentConnection) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); + private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { + actionHandler = new WebWhoisActionHandler( + bootstrap, + STANDARD_PROTOCOL, + STANDARD_PROTOCOL, + messageTemplate + ); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - setupProbingActionBasic( - protocol, - outboundMessage, - makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); - channel.attr(PROBING_ACTION_KEY).set(probingAction); + channel.attr(PROTOCOL_KEY).set(protocol); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -107,25 +121,23 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } /**Sets up probingAction for when testing redirection */ - private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(TARGET_HOST) - .address(DEFAULT_ADDRESS) + private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setHost(TARGET_HOST) + .setChannel(channel) .build(); } - private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(host) - .address(address) + private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(addressString) .build(); } @@ -136,10 +148,11 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); - generateLocalAddress(); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, true); + setupChannel(initialProtocol, msg); //stores future @@ -151,7 +164,7 @@ public void testBasic_responseOk() throws Exception { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -161,16 +174,16 @@ public void testBasic_responseOk() throws Exception { //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure() { + public void testBasic_responseFailure_badRequest() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseBad", 0); - generateLocalAddress(); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseBad", 0, true); setupChannel(initialProtocol, msg); //stores future @@ -181,8 +194,7 @@ public void testBasic_responseFailure() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage - .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -191,18 +203,18 @@ public void testBasic_responseFailure() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testBasic_responseError() { + public void testBasic_responseFailure_badURL() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseError", 0); - generateLocalAddress(); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseError", 0, true); setupChannel(initialProtocol, msg); //stores future @@ -213,7 +225,7 @@ public void testBasic_responseError() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -222,29 +234,31 @@ public void testBasic_responseError() { //assesses that listener is triggered, and event is success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(future.cause() instanceof FailureException); } @Test public void testBasic_redirectCloseChannel() { //setup - HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", 0); - generateLocalAddress(); - setupChannel(initialProtocol, outboundMessage); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", 0, true); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(outboundMessage); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -258,44 +272,15 @@ public void testBasic_redirectCloseChannel() { } @Test - public void testBasic_redirectHost() { - //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); - generateLocalAddress(); - setupChannel(initialProtocol, msg); - HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); - - - //store future - ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); - - - channel.writeInbound(originalResponse); - - ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); - - //gets changed protocol - Protocol newProtocol = newAction.protocol(); - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); - assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); - } - - @Test - public void testAdvanced_responseOk() { + public void testAdvanced_responseOk() throws UndeterminedStateException { //setup EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); - generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); - setupLocalServer("", TARGET_HOST, group); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); + setupActionHandler(null, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); @@ -305,21 +290,21 @@ public void testAdvanced_responseOk() { } @Test - public void testAdvanced_responseFailure() { + public void testAdvanced_responseFailure() throws UndeterminedStateException { //setup EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); - generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); - setupLocalServer("", TARGET_HOST, group); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(null, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + assertThrows(FailureException.class, future::syncUninterruptibly); } } From abc079d490f46e86a4d4a37e2dacbf2406600b0e Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:48:33 -0400 Subject: [PATCH 233/337] SpotlessApply run to fix style issues --- prober/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index 77b1e2de2de..c86568e7672 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From 75ece91ef33452863d86a5ef990f6b5ee4b7b8c8 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:28:40 -0400 Subject: [PATCH 234/337] Added license header and newline where appropriate. --- prober/build.gradle | 1 + .../monitoring/blackbox/ProbingAction.java | 1 - .../blackbox/handlers/ActionHandler.java | 2 +- .../monitoring/blackbox/ProbingSequenceTest.java | 14 ++++++++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index e48eacb8bf9..86d1bcb0051 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -37,6 +37,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] + compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 67494dd5f78..a8740e21c20 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -240,7 +240,6 @@ public ProbingAction build() { InetAddress hostAddress = InetAddress.getByName(host()); address = new InetSocketAddress(hostAddress, protocol().port()); } catch (UnknownHostException e) { - System.out.println("test"); address = new LocalAddress(host()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 0c9e93cc6dd..8a108b81006 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -97,4 +97,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } -} \ No newline at end of file +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2a8d5ebe233..8d9e45c6a66 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; From 3509b96506f2b6493ec54be3dcd114a57870afc2 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 235/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/ProbingStepTest.java | 1 - .../blackbox/TestServers/WebWhoisServer.java | 3 +- .../monitoring/blackbox/TestUtils.java | 35 +------------------ .../blackbox/handlers/ConversionHandler.java | 5 ++- .../blackbox/handlers/NettyRule.java | 16 ++++++--- 5 files changed, 18 insertions(+), 42 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 7bba9d66782..73b104ae5dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -174,7 +174,6 @@ public void testNewChannel() throws Exception { //checks that when the future is successful, we pass down the requisite token assertThat(future.get()).isEqualTo(testToken); - } @Test diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 06b19ea3607..9c84b9bd26d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; @@ -80,7 +81,7 @@ static class RedirectHandler extends ChannelDuplexHandler { /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 68bdd0bcef0..cc8e1512fe9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; @@ -28,17 +27,13 @@ import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpMethod;; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; import java.net.SocketAddress; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -272,33 +267,5 @@ public void addToHost(String suffix) { } } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..7e6d419a1e7 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b6b5e8fbe0c..1d14cf131e6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -26,6 +26,9 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.ProbingActionTest; +import google.registry.monitoring.blackbox.ProbingStepTest; +import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; @@ -53,7 +56,7 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -89,7 +92,8 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - ProbingAction probingAction, + Protocol protocol, + String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -109,7 +113,9 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROBING_ACTION_KEY, probingAction); + .attr(PROTOCOL_KEY, protocol) + .attr(REMOTE_ADDRESS_KEY, host); + channel = b.connect(localAddress).syncUninterruptibly().channel(); } From 1b018039bc3dd77b5d5a8bc6e00870e54d02c78f Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 17:01:14 -0400 Subject: [PATCH 236/337] Fixed files to pass all style tests --- .../registry/monitoring/blackbox/Prober.java | 10 +- .../monitoring/blackbox/ProberModule.java | 32 ++- .../monitoring/blackbox/ProbingAction.java | 260 +++++++++--------- .../monitoring/blackbox/ProbingSequence.java | 39 ++- .../monitoring/blackbox/ProbingStep.java | 79 +++--- .../monitoring/blackbox/Protocol.java | 16 +- .../monitoring/blackbox/WebWhoisModule.java | 92 +++++-- .../exceptions/ConnectionException.java | 4 +- .../UndeterminedStateException.java | 5 +- .../blackbox/handlers/ActionHandler.java | 53 ++-- .../handlers/SslClientInitializer.java | 11 +- .../handlers/WebWhoisActionHandler.java | 58 ++-- .../handlers/WebWhoisMessageHandler.java | 21 +- .../blackbox/messages/HttpRequestMessage.java | 19 +- .../messages/HttpResponseMessage.java | 6 +- .../blackbox/messages/InboundMessageType.java | 23 ++ .../messages/OutboundMessageType.java | 10 +- .../monitoring/blackbox/tokens/Token.java | 41 ++- .../blackbox/tokens/WebWhoisToken.java | 36 ++- .../blackbox/ProbingActionTest.java | 162 ++++++----- .../monitoring/blackbox/ProbingStepTest.java | 215 ++++++++------- .../blackbox/TestServers/TestServer.java | 99 ------- .../monitoring/blackbox/TestUtils.java | 187 ++----------- .../blackbox/handlers/ConversionHandler.java | 20 +- .../blackbox/handlers/NettyRule.java | 81 ++++-- .../handlers/SslClientInitializerTest.java | 73 ++--- .../blackbox/handlers/TestActionHandler.java | 4 +- .../handlers/WebWhoisActionHandlerTest.java | 238 ++++++---------- .../blackbox/testservers/TestServer.java | 91 +++--- .../WebWhoisServer.java | 61 ++-- 30 files changed, 971 insertions(+), 1075 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java rename prober/src/test/java/google/registry/monitoring/blackbox/{TestServers => testservers}/WebWhoisServer.java (62%) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 307afd34d81..a4d78495826 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -18,12 +18,16 @@ import java.util.Set; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by + * Dagger. */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + /** + * Main Dagger Component + */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() + .build(); public static void main(String[] args) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 1db97d1b581..bf9b93d6913 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -30,36 +30,50 @@ import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores - * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. + * Dagger main module, which {@link Provides} all objects that are shared between sequences and + * stores {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link + * ProbingSequence}. */ @Module public class ProberModule { - /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + /** + * Default {@link Duration} chosen to be time between each {@link ProbingAction} call. + */ private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ + /** + * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. + */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + /** + * {@link Provides} one global {@link Channel} class that is used to construct a {@link + * io.netty.bootstrap.Bootstrap}. + */ @Provides @Singleton Class provideChannelClass() { return NioSocketChannel.class; } - /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ + + /** + * {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. + */ @Provides @Singleton Duration provideDuration() { return DEFAULT_DURATION; } - /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ + /** + * {@link Provides} the {@link SslProvider} used by instances of {@link + * google.registry.monitoring.blackbox.handlers.SslClientInitializer} + */ @Provides @Singleton static SslProvider provideSslProvider() { @@ -67,7 +81,9 @@ static SslProvider provideSslProvider() { return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - /** Root level {@link Component} that provides each {@link ProbingSequence}. */ + /** + * Root level {@link Component} that provides each {@link ProbingSequence}. + */ @Singleton @Component( modules = { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index a8740e21c20..cdb099e4a76 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -26,42 +26,42 @@ import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.local.LocalAddress; -import io.netty.util.AttributeKey; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; +import io.netty.util.AttributeKey; import io.netty.util.HashedWheelTimer; import io.netty.util.Timer; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import javax.inject.Provider; +import org.joda.time.Duration; /** * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the - * task has been completed

+ * to perform its specified task, and return the {@link ChannelFuture} that will be informed when + * the task has been completed

* - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. - * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} - * gives the outline and {@link ProbingAction} gives the details of that connection.

+ *

Is an immutable class, as it is comprised of the tools necessary for making a specific type + * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall + * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the + * details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes + * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when + * informed that the connection is successful. If the channel is supplied, the connection future is + * automatically set to successful.

*/ @AutoValue @@ -69,133 +69,140 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** + * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when + * channel is active. + */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey + .valueOf("CONNECTION_FUTURE_KEY"); - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + /** + * {@link AttributeKey} in channel that gives the information of the channel's host. + */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey + .valueOf("REMOTE_ADDRESS_KEY"); - /** {@link Timer} that rate limits probing */ + /** + * {@link Timer} that rate limits probing + */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ + /** + * Actual {@link Duration} of this delay + */ public abstract Duration delay(); - /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ + /** + * {@link OutboundMessageType} instance that we write and flush down pipeline to server + */ public abstract OutboundMessageType outboundMessage(); - /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + /** + * {@link Channel} object that either created by or passed into this {@link ProbingAction} + * instance + */ + @Nullable public abstract Channel channel(); - /** The {@link Protocol} instance that specifies type of connection */ + /** + * The {@link Protocol} instance that specifies type of connection + */ public abstract Protocol protocol(); - /** The hostname of the remote host we have a connection or will make a connection to */ + /** + * The hostname of the remote host we have a connection or will make a connection to + */ public abstract String host(); - - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } - /** - * The method that performs the work of the actual action. + * Performs the work of the actual action + * + *

First, checks if channel is active by setting a listener to perform the bulk of the work + * when the connection future is successful.

* - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ *

Once the connection is successful, we establish which of the handlers in the pipeline is + * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when + * we receive an expected response from the server.

+ * + *

Next, we set a timer set to a specified delay. After the delay has passed, we send the + * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, + * we inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - - //ChannelPromise that we use to inform ProbingStep when we are finished. - ChannelPromise finished = channel().newPromise(); - - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - return finished; - } - - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + /** + * Method that calls on {@code performAction} when it is certain channel connection is + * established. + */ @Override - public ChannelFuture call() throws UndeterminedStateException { + public ChannelFuture call() { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); + + //Ensures channel has been set up with connection future as an attribute + checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + //When connection is established call super.call and set returned listener to success channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { + (ChannelFuture connectionFuture) -> { + if (connectionFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); + ActionHandler actionHandler; + try { + actionHandler = channel().pipeline().get(ActionHandler.class); + } catch (ClassCastException e) { + //If we don't actually have an ActionHandler instance, we have an issue, and throw + // an UndeterminedStateException + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); + } + ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture unusedFutureWriteAndFlush = + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> { + if (future.isSuccess()) { + ChannelFuture unusedFuture = finished.setSuccess(); + } else { + ChannelFuture unusedFuture = finished.setFailure(future.cause()); + } + }, + //If we don't have a persistent connection, close the connection to this + // channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) { + logger.atInfo() + .log("Closed stale channel. Moving on to next ProbingStep"); + } else { + logger.atWarning() + .log( + "Could not close channel. Stale connection still exists" + + "."); + } + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); } else { //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( + logger.atSevere().withCause(connectionFuture.cause()).log( "Cannot connect to relay channel for %s channel: %s.", protocol().name(), this.channel()); ChannelFuture unusedFuture = channel().close(); @@ -206,9 +213,12 @@ public ChannelFuture call() throws UndeterminedStateException { } - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + /** + * {@link AutoValue.Builder} that does work of creating connection when not already present. + */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; public Builder setBootstrap(Bootstrap bootstrap) { @@ -228,7 +238,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract Protocol protocol(); - abstract Optional channel(); + abstract Channel channel(); abstract String host(); @@ -243,11 +253,12 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + checkArgument(channel() == null ^ bootstrap == null, + "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { + if (channel() == null) { bootstrap.handler( new ChannelInitializer() { @Override @@ -293,14 +304,13 @@ private static void addHandlers( } - @Override - public String toString() { + public final String toString() { return String.format( - "ProbingAction with delay: %d\n" + - "outboundMessage: %s\n" + - "protocol: %s\n" + - "host: %s\n", + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 91c4165c068..175cf4dcfa5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -23,16 +23,21 @@ * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * * - *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

+ *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} + * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one + * is the first repeated step.

* - *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

+ *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once + * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest + * of the work.

*/ public class ProbingSequence { + private ProbingStep firstStep; - /**Each {@link ProbingSequence} requires a start token to begin running. */ + /** + * Each {@link ProbingSequence} requires a start token to begin running. + */ private Token startToken; public void start() { @@ -41,8 +46,8 @@ public void start() { } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link + * Bootstrap}. */ public static class Builder { @@ -57,33 +62,37 @@ public Builder(Token startToken) { } /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, - * built, and pointed to by the previous {@link ProbingStep} added. + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, built, and pointed to by + * the previous {@link ProbingStep} added. */ public Builder addStep(ProbingStep step) { - if (currentStep == null) + if (currentStep == null) { firstStep = step; - else + } else { currentStep.nextStep(step); + } currentStep = step; return this; } - /** We take special note of the first repeated step. */ + /** + * We take special note of the first repeated step. + */ public Builder markFirstRepeated() { firstRepeatedStep = currentStep; return this; } /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and - * calls private constructor to create {@link ProbingSequence}. + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private + * constructor to create {@link ProbingSequence}. */ public ProbingSequence build() { - if (firstRepeatedStep == null) + if (firstRepeatedStep == null) { firstRepeatedStep = firstStep; + } currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index ca980100067..98867c01220 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -17,47 +17,59 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import java.util.function.Consumer; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step - * in {@link ProbingSequence}. + * {@link AutoValue} class that represents generator of actions performed at each step in {@link + * ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. - * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, - * generates a new {@link ProbingAction} to call.

- * + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} + * instances. It then modifies these components on each loop iteration with the consumed {@link + * Token} and from that, generates a new {@link ProbingAction} to call.

*/ @AutoValue public abstract class ProbingStep implements Consumer { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Necessary boolean to inform when to obtain next {@link Token}*/ + /** + * Necessary boolean to inform when to obtain next {@link Token} + */ protected boolean isLastStep = false; private ProbingStep nextStep; - /** Time delay duration between actions. */ + /** + * Time delay duration between actions. + */ abstract Duration duration(); - /** {@link Protocol} type for this step. */ + /** + * {@link Protocol} type for this step. + */ abstract Protocol protocol(); - /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ + /** + * {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. + */ abstract OutboundMessageType messageTemplate(); - /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ + /** + * {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation + * of new channels. + */ abstract Bootstrap bootstrap(); + /** Default {@link AutoValue.Builder} for {@link ProbingStep}. */ @AutoValue.Builder - public static abstract class Builder { + public abstract static class Builder { + public abstract Builder setDuration(Duration value); public abstract Builder setProtocol(Protocol value); @@ -85,7 +97,9 @@ ProbingStep nextStep() { return this.nextStep; } - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ + /** + * Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} + */ private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() @@ -94,29 +108,33 @@ private ProbingAction generateAction(Token token) throws UndeterminedStateExcept .setOutboundMessage(message) .setHost(token.host()); - if (token.channel() != null) + if (token.channel() != null) { probingActionBuilder.setChannel(token.channel()); - else + } else { probingActionBuilder.setBootstrap(bootstrap()); + } return probingActionBuilder.build(); } - /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ + /** + * On the last step, gets the next {@link Token}. Otherwise, uses the same one. + */ private Token generateNextToken(Token token) { - return (isLastStep) ? token.next() : token; + return isLastStep ? token.next() : token; } /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the + * action. * * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. * *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

+ * we note an error. Otherwise, if the future marked as finished when the action is completed is + * marked as a success, we note a success. Otherwise, if the cause of failure will either be a + * failure or error.

*/ @Override public void accept(Token token) { @@ -124,18 +142,17 @@ public void accept(Token token) { //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(UndeterminedStateException e) { + } catch (UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - ChannelFuture future; try { //call the generated action future = currentAction.call(); - } catch(UndeterminedStateException e) { + } catch (Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); @@ -144,7 +161,6 @@ public void accept(Token token) { return; } - future.addListener(f -> { if (f.isSuccess()) { //On a successful result, we log as a successful step, and not a success @@ -155,9 +171,10 @@ public void accept(Token token) { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - if (protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token + if (protocol().persistentConnection()) { + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + } //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); @@ -167,9 +184,9 @@ public void accept(Token token) { } @Override - public String toString() { - return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n", + public final String toString() { + return String.format("ProbingStep with Protocol: %s\n" + + "OutboundMessage: %s\n", protocol(), messageTemplate().getClass().getName()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 92470ef62c8..e524e787742 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -26,23 +26,30 @@ @AutoValue public abstract class Protocol { - /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + /** + * {@link AttributeKey} that lets channel reference {@link Protocol} that created it. + */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); public abstract String name(); public abstract int port(); - /** The {@link ChannelHandler} providers to use for the protocol, in order. */ + /** + * The {@link ChannelHandler} providers to use for the protocol, in order. + */ abstract ImmutableList> handlerProviders(); - /** Boolean that notes if connection associated with Protocol is persistent.*/ + /** + * Boolean that notes if connection associated with Protocol is persistent. + */ abstract boolean persistentConnection(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } + /** Default {@link AutoValue.Builder} for {@link Protocol}. */ @AutoValue.Builder public abstract static class Builder { @@ -50,7 +57,8 @@ public abstract static class Builder { public abstract Builder setPort(int num); - public abstract Builder setHandlerProviders(ImmutableList> providers); + public abstract Builder setHandlerProviders( + ImmutableList> providers); public abstract Builder setPersistentConnection(boolean value); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index c5e41fea38b..55fc7cf71a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,14 +17,11 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -33,16 +30,15 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; import org.joda.time.Duration; -/** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ +/** + * A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. + */ @Module public class WebWhoisModule { @@ -51,23 +47,39 @@ public class WebWhoisModule { private static final String HTTP_PROTOCOL_NAME = "http"; private static final String HTTPS_PROTOCOL_NAME = "https"; - /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + /** + * Standard length of messages used by Proxy. Equates to 0.5 MB. + */ private static final int maximumMessageLengthBytes = 512 * 1024; - /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ + /** + * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. + */ @Qualifier - public @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol { - /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ + } + + /** + * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. + */ @Qualifier - public @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol { + + } - /** Dagger qualifier to provide any WebWhois related bindings. */ + /** + * Dagger qualifier to provide any WebWhois related bindings. + */ @Qualifier - public @interface WebWhoisProtocol {} + public @interface WebWhoisProtocol { + + } - /** {@link Provides} standard WebWhois sequence. */ + /** + * {@link Provides} standard WebWhois sequence. + */ @Provides @Singleton @IntoSet @@ -81,7 +93,9 @@ ProbingSequence provideWebWhoisSequence( } - /** {@link Provides} only step used in WebWhois sequence. */ + /** + * {@link Provides} only step used in WebWhois sequence. + */ @Provides @WebWhoisProtocol static ProbingStep provideWebWhoisStep( @@ -98,7 +112,9 @@ static ProbingStep provideWebWhoisStep( .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ + /** + * {@link Provides} the {@link Protocol} that corresponds to http connection. + */ @Singleton @Provides @HttpWhoisProtocol @@ -113,7 +129,9 @@ static Protocol provideHttpWhoisProtocol( .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ + /** + * {@link Provides} the {@link Protocol} that corresponds to https connection. + */ @Singleton @Provides @HttpsWhoisProtocol @@ -129,7 +147,10 @@ static Protocol provideHttpsWhoisProtocol( } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ + /** + * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http + * protocol. + */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( @@ -144,11 +165,15 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ + /** + * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https + * protocol. + */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( - @HttpsWhoisProtocol Provider> sslClientInitializerProvider, + @HttpsWhoisProtocol + Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, Provider messageHandlerProvider, @@ -171,23 +196,28 @@ static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int ma return new HttpObjectAggregator(maxContentLength); } - /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + /** + * {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. + */ @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + static SslClientInitializer provideSslClientInitializer( + SslProvider sslProvider) { return new SslClientInitializer<>(sslProvider); } - /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + /** + * {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. + */ @Singleton @Provides @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClass){ + Class channelClazz) { return new Bootstrap() .group(eventLoopGroup) - .channel(channelClass); + .channel(channelClazz); } @Provides @@ -196,12 +226,14 @@ int provideMaximumMessageLengthBytes() { return maximumMessageLengthBytes; } - /** {@link Provides} the list of top level domains to be probed */ + /** + * {@link Provides} the list of top level domains to be probed + */ @Singleton @Provides @WebWhoisProtocol ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); + return ImmutableList.of("how", "soy", "xn--q9jyb4c"); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index adb833ec629..776a231d6dd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,8 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when - * the action performed failed due to an issue in the connection with the server. + * Subclass of {@link UndeterminedStateException} that represents all instances when the action + * performed failed due to an issue in the connection with the server. */ public class ConnectionException extends UndeterminedStateException { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java index c155d695c7f..d7127717d52 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java @@ -15,9 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails - * before we can determine the state of the result, meaning the status - * is recorded as ERROR. + * Base exception class for all instances when the action performed fails before we can determine + * the state of the result, meaning the status is recorded as ERROR. */ public class UndeterminedStateException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 8a108b81006..6552bca3eca 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -16,25 +16,30 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; /** - *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline + * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType + * >}, as it should only be passed in messages that implement the {@link InboundMessageType} + * interface.

* - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} - * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a + * {@link + * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this + * channel is informed of the error. If the error is an instance of a {@link FailureException} + * {@code finished} is marked as a failure with cause {@link FailureException}. If it is any other + * type of error, it is treated as an {@link UndeterminedStateException} and {@code finished} set as + * a failure with the same cause as what caused the exception. Lastly, if no error is thrown, we + * know the action completed as a success, and, as such, we mark {@code finished} as a success.

* *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ @@ -42,32 +47,40 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler privateKeySupplier, Supplier certificateSupplier) { + public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, + Supplier certificateSupplier) { //We use the default trust store here as well, setting trustCertificates to null this(sslProvider, null, privateKeySupplier, certificateSupplier); } @@ -99,8 +98,10 @@ protected void initChannel(C channel) throws Exception { SslContextBuilder.forClient() .sslProvider(sslProvider) .trustManager(trustedCertificates); - if (privateKeySupplier != null && certificateSupplier != null) - sslContextBuilder = sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get()); + if (privateKeySupplier != null && certificateSupplier != null) { + sslContextBuilder = sslContextBuilder + .keyManager(privateKeySupplier.get(), certificateSupplier.get()); + } SslHandler sslHandler = sslContextBuilder .build() diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 1ec4e314813..c0f7ce8ae78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,17 +14,15 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; @@ -38,10 +36,11 @@ import org.joda.time.Duration; /** - *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection - * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

+ *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response + * implies a redirection it follows the redirection until either an Error Response is received, or + * {@link HttpResponseStatus.OK} is received

*/ public class WebWhoisActionHandler extends ActionHandler { @@ -49,16 +48,24 @@ public class WebWhoisActionHandler extends ActionHandler { /** Dagger injected components necessary for redirect responses: */ - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + /** + * {@link Bootstrap} necessary for remaking connection on redirect response. + */ private final Bootstrap bootstrap; - /** {@link Protocol} for when redirected to http endpoint. */ + /** + * {@link Protocol} for when redirected to http endpoint. + */ private final Protocol httpWhoisProtocol; - /** {@link Protocol} for when redirected to https endpoint. */ + /** + * {@link Protocol} for when redirected to https endpoint. + */ private final Protocol httpsWhoisProtocol; - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + /** + * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. + */ private final HttpRequestMessage requestMessage; @Inject @@ -76,9 +83,10 @@ public WebWhoisActionHandler( /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, + * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a + * response indicating a Failure, or receives a redirection response, where it follows the + * redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) @@ -86,14 +94,14 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { + if (response.status().equals(HttpResponseStatus.OK)) { logger.atInfo().log("Received Successful HttpResponseStatus"); logger.atInfo().log("Response Received: " + response); //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); - } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { + } else if (response.headers().get("location") != null) { //Obtain url to be redirected to URL url; @@ -101,14 +109,17 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException( + "Redirected Location was invalid. Given Location was: " + response.headers() + .get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); - int newPort = url.getDefaultPort(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); + logger.atInfo().log(String + .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, + url.getDefaultPort(), newPath)); //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; @@ -117,7 +128,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException( + "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -142,10 +154,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atWarning().log("Channel was unsuccessfully closed."); } - //Once channel is closed, establish new connection to redirected host, and repeat same actions + //Once channel is closed, establish new connection to redirected host, and repeat + // same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + //Once we have a successful call, set original ChannelPromise as success to tell + // ProbingStep we can move on secondFuture.addListener(f2 -> { if (f2.isSuccess()) { super.channelRead0(ctx, msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 58c395ad86e..576d6a04d42 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -24,25 +24,32 @@ import javax.inject.Inject; /** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} - * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection. + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom + * type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for + * redirection. */ public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject - public WebWhoisMessageHandler() {} + public WebWhoisMessageHandler() { + } - /** Retains {@link HttpRequestMessage} and calls super write method. */ + /** + * Retains {@link HttpRequestMessage} and calls super write method. + */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) + throws Exception { HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ + /** + * Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link + * InboundMessageType} instance. + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b4c01d06a8f..745a360cab5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -25,8 +25,8 @@ * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. * *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

+ * that modifies the request to reflect the new host and optional path. We also implement a {@code + * name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { @@ -38,7 +38,9 @@ public HttpRequestMessage() { private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, + ByteBuf content) { super(httpVersion, method, uri, content); } @@ -49,19 +51,24 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ + /** + * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} + */ public HttpRequestMessage(FullHttpRequest request) { this(request.protocolVersion(), request.method(), request.uri(), request.content()); request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } - /** Modifies headers to reflect new host and new path if applicable. */ + /** + * Modifies headers to reflect new host and new path if applicable. + */ @Override public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { if (args.length == 1 || args.length == 2) { headers().set("host", args[0]); - if (args.length == 2) + if (args.length == 2) { setUri(args[1]); + } return this; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index f1b2d6ac6a7..7d2ff722076 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -29,8 +29,10 @@ private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, Byte super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { + /** + * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} + */ + public HttpResponseMessage(FullHttpResponse response) { this(response.protocolVersion(), response.status(), response.content()); response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java new file mode 100644 index 00000000000..0a584dfa2a7 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -0,0 +1,23 @@ +// Copyright 2019 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.monitoring.blackbox.messages; + +/** + * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in + * channel pipeline + */ +public interface InboundMessageType { + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index d8a28c25dbd..4a7c16243cd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -22,10 +22,16 @@ */ public interface OutboundMessageType { - /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + /** + * All {@link OutboundMessageType} implementing classes should be able to be modified by token + * with String arguments + */ OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; - /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + /** + * Necessary to inform metrics collector what kind of message is sent down {@link + * io.netty.channel.ChannelPipeline} + */ @Override String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dab5851e8d8..b10c45dae8a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,19 +14,19 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.ProbingSequence; import google.registry.monitoring.blackbox.ProbingStep; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} - * in a single loop of a {@link ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} in a single loop of a + * {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes - * on channel that remains unchanged within a loop of the sequence.

+ * in a {@link ProbingSequence}. Additionally, passes on channel that remains unchanged within a + * loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop * in the sequence.

@@ -34,27 +34,38 @@ public abstract class Token { /** - * {@link Channel} that always starts out as null. Once a persistent connection - * is made (such as EPP), that channel is stored in the token and passed on to - * later steps in the sequence until a new loop begins. + * {@link Channel} that always starts out as null. Once a persistent connection is made (such as + * EPP), that channel is stored in the token and passed on to later steps in the sequence until a + * new loop begins. */ protected Channel channel; - /** Obtains next {@link Token} for next loop in sequence. */ + /** + * Obtains next {@link Token} for next loop in sequence. + */ public abstract Token next(); - /** String corresponding to host that is relevant for loop in sequence. */ + /** + * String corresponding to host that is relevant for loop in sequence. + */ public abstract String host(); - /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; + /** + * Modifies the {@link OutboundMessageType} in the manner necessary for each loop + */ + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) + throws UndeterminedStateException; - /** Set method for {@code channel} */ + /** + * Set method for {@code channel} + */ public void setChannel(Channel channel) { this.channel = channel; } - /** Get method for {@code channel}. */ + /** + * Get method for {@code channel}. + */ public Channel channel() { return this.channel; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index bb06ee89db6..3ff852f3556 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -19,26 +19,30 @@ import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import java.util.Iterator; -import java.util.LinkedList; import javax.inject.Inject; -import javax.inject.Named; /** * {@link Token} subtype designed for WebWhois sequence. * *

Between loops of a WebWhois sequence the only thing changing is the tld we - * are probing. As a result, we maintain the list of {@code topLevelDomains} and - * on each call to next, have our index looking at the next {@code topLevelDomain}.

+ * are probing. As a result, we maintain the list of {@code topLevelDomains} and on each call to + * next, have our index looking at the next {@code topLevelDomain}.

*/ public class WebWhoisToken extends Token { - /** For each top level domain (tld), we probe "prefix.tld". */ - private final static String PREFIX = "whois.nic."; + /** + * For each top level domain (tld), we probe "prefix.tld". + */ + private static final String PREFIX = "whois.nic."; - /** {@link ImmutableList} of all top level domains to be probed. */ + /** + * {@link ImmutableList} of all top level domains to be probed. + */ private final Iterator topLevelDomainsIterator; - /** Current index of {@code topLevelDomains} that represents tld we are probing. */ + /** + * Current index of {@code topLevelDomains} that represents tld we are probing. + */ private String currentDomain; @Inject @@ -48,20 +52,28 @@ public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { currentDomain = topLevelDomainsIterator.next(); } - /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ + /** + * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. + */ @Override public WebWhoisToken next() { currentDomain = topLevelDomainsIterator.next(); return this; } - /** Modifies message to reflect the new host coming from the new top level domain. */ + /** + * Modifies message to reflect the new host coming from the new top level domain. + */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + public OutboundMessageType modifyMessage(OutboundMessageType original) + throws UndeterminedStateException { return original.modifyMessage(host()); } - /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ + /** + * Returns host as the concatenation of fixed {@code prefix} and current value of {@code + * topLevelDomains}. + */ @Override public String host() { return PREFIX + currentDomain; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index 817d7245b1f..6cfb235d97c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,17 +20,14 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -41,115 +38,88 @@ import io.netty.channel.nio.NioEventLoopGroup; import javax.inject.Provider; import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; + /** * Unit tests for {@link ProbingAction} subtypes * *

Attempts to test how well each {@link ProbingAction} works with an {@link ActionHandler} * subtype when receiving to all possible types of responses

- * */ + */ @RunWith(JUnit4.class) public class ProbingActionTest { - /** Necessary Constants for test */ - private final String TEST_MESSAGE = "MESSAGE_TEST"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final int TEST_PORT = 0; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - private Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); - - /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ + + private static final String TEST_MESSAGE = "MESSAGE_TEST"; + private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private static final String ADDRESS_NAME = "TEST_ADDRESS"; + private static final int TEST_PORT = 0; + + private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + + /** + * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on + * {@link ProbingAction} + */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - private ProbingAction newChannelAction; - private ProbingAction existingChannelAction; - private EmbeddedChannel channel; - private Protocol protocol; + private Provider testHandlerProvider = () -> testHandler; + private Provider conversionHandlerProvider = () -> conversionHandler; - /** Used for testing how well probing step can create connection to blackbox server */ + /** + * Used for testing how well probing step can create connection to blackbox server + */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** Sets up a {@link Protocol} corresponding to when a new connection is created */ - private void setupNewChannelProtocol() { - protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - } - /** Sets up a {@link Protocol} corresponding to when a new connection exists */ - private void setupExistingChannelProtocol() { - protocol = Protocol.builder() + + @Ignore + @Test + public void testBehavior_existingChannel() { + //setup + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up a Protocol corresponding to when a connection exists. + Protocol protocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) .build(); - } - - /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ - private void setupNewChannelAction() { - newChannelAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - } - private void setupChannel() { - channel = new EmbeddedChannel(); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - - /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ - private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ProbingAction.builder() + // Sets up a ProbingAction that creates a channel using test specified attributes. + ProbingAction action = ProbingAction.builder() .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost("") .build(); - } - - @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { - //setup - setupChannel(); - setupExistingChannelProtocol(); - channel.pipeline().addLast(conversionHandler); - channel.pipeline().addLast(testHandler); - setupExistingChannelAction(channel); - - ChannelFuture future = existingChannelAction.call(); + //tests main function of ProbingAction + ChannelFuture future = action.call(); - //Ensures that we pass in the right message to the channel and haven't marked the future as success yet - Object msg = channel.readOutbound(); + //Obtains the outboundMessage passed through pipeline after delay + Object msg = null; + while (msg == null) { + msg = channel.readOutbound(); + } + //tests the passed message is exactly what we expect assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - assertThat(response).isEqualTo(TEST_MESSAGE); - assertThat(future.isSuccess()).isFalse(); + String request = ((ByteBuf) msg).toString(UTF_8); + assertThat(request).isEqualTo(TEST_MESSAGE); + + // Ensures that we haven't marked future as done until response is received. + assertThat(future.isDone()).isFalse(); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -158,19 +128,41 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { @Test public void testSuccess_newChannel() throws Exception { //setup - setupNewChannelProtocol(); + + LocalAddress address = new LocalAddress(ADDRESS_NAME); + Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + // Sets up a Protocol corresponding to when a new connection is created. + Protocol protocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) + .build(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - setupNewChannelAction(); - ChannelFuture future = newChannelAction.call(); + + // Sets up a ProbingAction with existing channel using test specified attributes. + ProbingAction action = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) + .build(); + + //tests main function of ProbingAction + ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); - future.sync(); + future = future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()); - assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()).isTrue(); + assertThat(((TestActionHandler) testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 73b104ae5dc..307d19221dd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,200 +11,203 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.TestUtils.dummyStep; -import static google.registry.monitoring.blackbox.TestUtils.testStep; -import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; +import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +/** + * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific + * implementations + */ public class ProbingStepTest { - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + /** + * Basic Constants necessary for tests + */ + private static final String ADDRESS_NAME = "TEST_ADDRESS"; + private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private static final int PROTOCOL_PORT = 0; + private static final String TEST_MESSAGE = "TEST_MESSAGE"; + private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private static final LocalAddress ADDRESS = new LocalAddress(ADDRESS_NAME); private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - /** Used for testing how well probing step can create connection to blackbox server */ + /** + * Used for testing how well probing step can create connection to blackbox server + */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + /** + * The two main handlers we need in any test pipeline used that connects to {@link NettyRule's + * server} + **/ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(ADDRESS_NAME); + /** + * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} + * is called, it just marks the supplied future as succeeded, returning the requisite token. + */ + private ProbingStep dummyStep() { + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(dummyStep).nextStep(); + return dummyStep; } - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); - dummyStep = dummyStep(eventLoopGroup); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - } + @Test + public void testNewChannel() throws Exception { + // Wrapper provider classes of handlers. + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() + // Sets up Protocol for when we create a new channel. + Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); - } - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) .build(); - } - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); - } + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); - @Test - public void testNewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + //Set up blackbox server that receives our messages then echoes them back to us + nettyRule.setUpServer(ADDRESS); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); + verify(dummyStep, times(1)).accept(any(Token.class)); } + @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupChannel(); - setupExistingChannelToken(); + // Wrapper provider classes of handlers. + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; + + // Sets up Protocol for when a channel already exists. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) + .build(); + + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) + .build(); + + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + + // Sets up an embedded channel to contain the two handlers we created already. + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + + //Assures that the channel has a succeeded connectionFuture. + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. + Token testToken = new ExistingChannelToken(channel, ""); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + //Call accept on the first step, which should send our message through the EmbeddedChannel + // pipeline firstStep.accept(testToken); - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + Object msg = channel.readOutbound(); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + while (msg == null) { + msg = channel.readOutbound(); + } + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf) channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); + //At this point, we should have received the message, so the future obtained should be marked + // as a success + verify(dummyStep, times(1)).accept(any(Token.class)); - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java deleted file mode 100644 index a4474b6b8b5..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; - -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; - -/** - * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform - */ -public abstract class TestServer { - private LocalAddress localAddress; - - TestServer(LocalAddress localAddress, ImmutableList handlers) { - this(new NioEventLoopGroup(1), localAddress, handlers); - } - - TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - this.localAddress = localAddress; - - //Creates ChannelInitializer with handlers specified - ChannelInitializer serverInitializer = new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) { - for (ChannelHandler handler : handlers) { - ch.pipeline().addLast(handler); - } - } - }; - //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using LocalServerChannel class - ServerBootstrap serverBootstrap = - new ServerBootstrap() - .group(eventLoopGroup) - .channel(LocalServerChannel.class) - .childHandler(serverInitializer); - - ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); - - } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index cc8e1512fe9..c0c5831a68c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,42 +16,24 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMethod;; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.concurrent.DefaultPromise; -import java.net.SocketAddress; -import javax.inject.Provider; -import org.joda.time.Duration; -/** Utility class for various helper methods used in testing. */ +/** + * Utility class for various helper methods used in testing. + */ public class TestUtils { - static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -72,144 +54,33 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { return response; } - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + /** + * Creates HttpResponse given status, redirection location, and other necessary inputs + */ public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); + response.headers().set("content-type", "text/plain"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } return response; } - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); - return response; - } - - /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ - public static class TestProvider implements Provider { - - private E obj; - - public TestProvider(E obj) { - this.obj = obj; - } - - @Override - public E get() { - return obj; - } - } - - /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ - public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { - - String message; - - public DuplexMessageTest() { - message = ""; - } - - public DuplexMessageTest(String msg) { - message = msg; - } - - @Override - public String toString() { - return message; - } - - @Override - public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { - message = args[0]; - return this; - } - } - - /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .build(); - - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); - } - - /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { - private DefaultPromise future; - - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; - } - - @Override - public void accept(Token token) { - future.setSuccess(token); - } - public DefaultPromise getFuture() { - return future; - } + /** + * Basic outline for {@link Token} instances to be used in tests + */ + abstract static class TestToken extends Token { - @Override - public String toString() { - return "Dummy Step"; - } - } - - /** Basic outline for {@link Token} instances to be used in tests */ - private static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { this.host = host; } + @Override public Token next() { return this; @@ -227,45 +98,29 @@ public String host() { } - /** {@link TestToken} instance that creates new channel */ + /** + * {@link TestToken} instance that creates new channel + */ public static class NewChannelToken extends TestToken { + public NewChannelToken(String host) { super(host); } + @Override public Channel channel() { return null; } } - /** {@link TestToken} instance that passes in existing channel */ + /** + * {@link TestToken} instance that passes in existing channel + */ public static class ExistingChannelToken extends TestToken { - private Channel channel; - public ExistingChannelToken(Channel channel, String host) { super(host); this.channel = channel; } - @Override - public Channel channel() { - return channel; - } - } - - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 7e6d419a1e7..987abbfd7dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -28,23 +28,27 @@ import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to - * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link + * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} + * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** Handles inbound conversion */ + /** + * Handles inbound conversion + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } - /** Handles outbound conversion */ + /** + * Handles outbound conversion + */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 1d14cf131e6..f51f8c8fd61 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -25,14 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -44,7 +41,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -55,24 +51,25 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

+ *

Code based on and almost identical to {@code NettyRule} in the proxy. + * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest} + *

*/ public final class NettyRule extends ExternalResource { - // All I/O operations are done inside the single thread within this event loop group, which is // different from the main test thread. Therefore synchronizations are required to make sure that // certain I/O activities are finished when assertions are performed. public NettyRule() { eventLoopGroup = new NioEventLoopGroup(1); } + public NettyRule(EventLoopGroup e) { eventLoopGroup = e; } + private final EventLoopGroup eventLoopGroup; - private WebWhoisServer webWhoisServer; // Handler attached to server's channel to record the request received. private EchoHandler echoHandler; @@ -82,14 +79,20 @@ public NettyRule(EventLoopGroup e) { private Channel channel; - /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + /** + * Sets up a server channel bound to the given local address. + */ + public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + + new WebWhoisServer(eventLoopGroup, localAddress, + ImmutableList.builder().add(handlers).add(echoHandler).build()); } - /** Sets up a client channel connecting to the give local address. */ + /** + * Sets up a client channel connecting to the give local address. + */ void setUpClient( LocalAddress localAddress, Protocol protocol, @@ -123,8 +126,10 @@ private void checkReady() { checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); } - /** Test that custom setup to send message to current server sends right message */ - public void assertThatCustomWorks(String message) throws Exception { + /** + * Test that custom setup to send message to current server sends right message + */ + public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -132,9 +137,9 @@ public void assertThatCustomWorks(String message) throws Exception { /** * Test that a message can go through, both inbound and outbound. * - *

The client writes the message to the server, which echos it back and saves the string in its - * promise. The client receives the echo and saves it in its promise. All these activities happens - * in the I/O thread, and this call itself returns immediately. + *

The client writes the message to the server, which echos it back and saves the string in + * its promise. The client receives the echo and saves it in its promise. All these activities + * happens in the I/O thread, and this call itself returns immediately. */ void assertThatMessagesWork() throws Exception { checkReady(); @@ -165,8 +170,42 @@ ThrowableSubject assertThatClientRootCause() { } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } - /** A handler that dumps its inbound message to a promise that can be inspected later. */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** + * Saves any inbound error as the cause of the promise failure. + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } + + /** + * A handler that dumps its inbound message to a promise that can be inspected later. + */ private static class DumpHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture responseFuture = new CompletableFuture<>(); @@ -187,7 +226,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception responseFuture.complete(response); } - /** Saves any inbound error into the failure cause of the promise. */ + /** + * Saves any inbound error into the failure cause of the promise. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 469c62a8f75..25e5608a100 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,18 +15,14 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ExistingChannelAction; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; @@ -45,7 +41,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; -import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,12 +62,14 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); - - /** Fake host to test if the SSL engine gets the correct peer host. */ + /** + * Fake host to test if the SSL engine gets the correct peer host. + */ private static final String SSL_HOST = "www.example.tld"; - /** Fake port to test if the SSL engine gets the correct peer port. */ + /** + * Fake port to test if the SSL engine gets the correct peer port. + */ private static final int SSL_PORT = 12345; @Rule @@ -85,23 +82,24 @@ public class SslClientInitializerTest { @Parameters(name = "{0}") public static SslProvider[] data() { return OpenSsl.isAvailable() - ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[] {SslProvider.JDK}; + ? new SslProvider[]{SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[]{SslProvider.JDK}; } - /** Saves the SNI hostname received by the server, if sent by the client. */ + /** + * Saves the SNI hostname received by the server, if sent by the client. + */ private String sniHostReceived; - /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .persistentConnection(false) - .build(); - - private ProbingAction probingAction; + /** + * Fake protocol saved in channel attribute. + */ + private static final Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -113,23 +111,13 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } - private void setupProbingAction(Channel channel) { - probingAction = ExistingChannelAction.builder() - .delay(Duration.ZERO) - .host(SSL_HOST) - .channel(channel) - .outboundMessage(DEFAULT_MESSAGE) - .protocol(PROTOCOL) - .build(); - } - @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - setupProbingAction(channel); - channel.attr(PROBING_ACTION_KEY).set(probingAction); + channel.attr(PROTOCOL_KEY).set(PROTOCOL); + channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -160,8 +148,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -187,10 +174,9 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -217,10 +203,9 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 3ecbdcc0d06..be42536823f 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -20,8 +20,8 @@ import io.netty.channel.ChannelHandlerContext; /** - * Concrete implementation of {@link ActionHandler} that does nothing different from - * parent class other than store and return the {@code inboundMessage} + * Concrete implementation of {@link ActionHandler} that does nothing different from parent class + * other than store and return the {@code inboundMessage} */ public class TestActionHandler extends ActionHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 2483bd65b1f..5a0d0908724 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -17,34 +17,27 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; -import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -57,36 +50,30 @@ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; - private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; - private static final String HTTPS_REDIRECT = "https://"; - private static final String REDIRECT_HOST = "www.example.com"; - private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of()) + private final Protocol standardProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( + null, null, null, null))) .setName("http") .setPersistentConnection(false) - .setPort(HTTPS_PORT) + .setPort(HTTP_PORT) .build(); - private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; - private ProbingAction probingAction; private Provider actionHandlerProvider; + private Protocol initialProtocol; + private HttpRequestMessage msg; - private String generateLocalAddress(String addressString) { - String modifiedAddress = addressString + System.currentTimeMillis(); - address = new LocalAddress(modifiedAddress); - return modifiedAddress; - } - /** Creates default protocol with empty list of handlers and specified other inputs */ + /** + * Creates default protocol with empty list of handlers and specified other inputs + */ private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() .setName(name) @@ -96,23 +83,26 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect .build(); } - /** Initializes new WebWhoisActionHandler */ + /** + * Initializes new WebWhoisActionHandler + */ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, - STANDARD_PROTOCOL, - STANDARD_PROTOCOL, + standardProtocol, + standardProtocol, messageTemplate ); - actionHandlerProvider = new TestProvider<>(actionHandler); + actionHandlerProvider = () -> actionHandler; } - /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + /** + * Sets up testing channel with requisite attributes + */ + private void setupChannel(Protocol protocol) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -120,192 +110,126 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .group(group) .channel(LocalChannel.class); } - /**Sets up probingAction for when testing redirection */ - private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setHost(TARGET_HOST) - .setChannel(channel) - .build(); - } - private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(addressString) - .build(); + private void setupLocalServer(String redirectInput, String destinationInput, + EventLoopGroup group, LocalAddress address) { + WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { - WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); + private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { + msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); + setupActionHandler(bootstrap, msg); + initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + } @Test - public void testBasic_responseOk() throws Exception { + public void testBasic_responseOk() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, true); - - setupChannel(initialProtocol, msg); + setup("", null, true); + setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure_badRequest() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseBad", 0, true); - setupChannel(initialProtocol, msg); + setup("", null, false); + setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage( + makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same assertThat(future.cause() instanceof FailureException).isTrue(); } - @Test - public void testBasic_responseFailure_badURL() { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseError", 0, true); - setupChannel(initialProtocol, msg); - - //stores future - ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, and event is success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); - } + @SuppressWarnings("CheckReturnValue") @Test - public void testBasic_redirectCloseChannel() { + public void testBasic_responseFailure_badURL() { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", 0, true); - setupChannel(initialProtocol, msg); + setup("", null, false); + setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - //checks that future has not been set to successful or a failure - assertThat(testPromise.isSuccess()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - + //assesses that listener is triggered, and event is success + assertThat(future.isDone()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + //ensures Protocol is the same + assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_responseOk() throws UndeterminedStateException { - //setup + public void testAdvanced_redirect() { + // Sets up EventLoopGroup with 1 thread to be blocking. EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); + + // Sets up embedded channel. + setup("", makeBootstrap(group), false); + setupChannel(initialProtocol); + + // Initializes LocalAddress with unique String. + String host = TARGET_HOST + System.currentTimeMillis(); + LocalAddress address = new LocalAddress(host); //stores future - ChannelFuture future = probingAction.call(); + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); - } + // Sets up the local server that the handler will be redirected to. + setupLocalServer("", host, group, address); - @Test - public void testAdvanced_responseFailure() throws UndeterminedStateException { - //setup - EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); + FullHttpResponse response = + new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, + HTTP_REDIRECT + host, true, false)); - //stores future - ChannelFuture future = probingAction.call(); + //checks that future has not been set to successful or a failure + assertThat(future.isDone()).isFalse(); + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); //assesses that we successfully received good response and protocol is unchanged - assertThrows(FailureException.class, future::syncUninterruptibly); + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java index c39fe554390..6c3c5feb492 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java @@ -14,39 +14,44 @@ package google.registry.monitoring.blackbox.testservers; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to * perform */ -public class TestServer { +public abstract class TestServer { + private LocalAddress localAddress; - public TestServer(LocalAddress localAddress, ImmutableList handlers) { + TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } - public TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, +<<<<<<<< HEAD:prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java + TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { +======== + TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + this.localAddress = localAddress; + +>>>>>>>> 949be9b42... Fixed files to pass all style tests:prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override @@ -67,57 +72,35 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } - - public static TestServer webWhoisServer(EventLoopGroup eventLoopGroup, - LocalAddress localAddress, String redirectInput, String destinationInput, - String destinationPath) { - return new TestServer( - eventLoopGroup, - localAddress, - ImmutableList.of(new RedirectHandler(redirectInput, destinationInput, destinationPath)) - ); - } - /** - * Handler that will wither redirect client, give successful response, or give error messge + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. */ - @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { + public static class EchoHandler extends ChannelInboundHandlerAdapter { - private String redirectInput; - private String destinationInput; - private String destinationPath; + private final CompletableFuture requestFuture = new CompletableFuture<>(); - /** - * @param redirectInput - Server will send back redirect to {@code destinationInput} when - * receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response - * when receiving a request with this host location - */ - public RedirectHandler(String redirectInput, String destinationInput, String destinationPath) { - this.redirectInput = redirectInput; - this.destinationInput = destinationInput; - this.destinationPath = destinationPath; + public Future getRequestFuture() { + return requestFuture; } - /** - * Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on - * what header location is - */ @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { - HttpResponse response; - if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true)); - } else if (request.headers().get("host").equals(destinationInput) - && request.uri().equals(destinationPath)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); - } - ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response); + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** Saves any inbound error as the cause of the promise failure. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); } } + } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java similarity index 62% rename from prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java rename to prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java index 9c84b9bd26d..d15a8a8e3a4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.TestServers; +package google.registry.monitoring.blackbox.testservers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; @@ -20,11 +20,12 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -36,30 +37,40 @@ * {@link TestServer} subtype that performs WebWhois Services Expected * *

It will either redirect the client to the correct location if given the - * requisite redirect input, give the client a successful response if they give - * the expected final destination, or give the client an error message if given - * an unexpected host location

+ * requisite redirect input, give the client a successful response if they give the expected final + * destination, or give the client an error message if given an unexpected host location

*/ public class WebWhoisServer extends TestServer { - public WebWhoisServer(LocalAddress localAddress, ImmutableList handlers) { + public WebWhoisServer(LocalAddress localAddress, + ImmutableList handlers) { super(localAddress, handlers); } - public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, + ImmutableList handlers) { super(eventLoopGroup, localAddress, handlers); } - /** Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the HttpRequestMessage object through pipeline */ - public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + /** + * Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the + * HttpRequestMessage object through pipeline + */ + public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, + LocalAddress localAddress, String redirectInput, String destinationInput) { return new WebWhoisServer( eventLoopGroup, localAddress, ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) ); } - /** Creates server that sends exactly what we expect a remote server to send as a response, by sending the {@link ByteBuf} of the response through pipeline */ - public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + + /** + * Creates server that sends exactly what we expect a remote server to send as a response, by + * sending the {@link ByteBuf} of the response through pipeline + */ + public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, + String redirectInput, String destinationInput) { return new WebWhoisServer( eventLoopGroup, localAddress, @@ -74,33 +85,39 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends ChannelDuplexHandler { + static class RedirectHandler extends SimpleChannelInboundHandler { + private String redirectInput; private String destinationInput; /** - * - * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location + * @param redirectInput - Server will send back redirect to {@code destinationInput} when + * receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response + * when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; this.destinationInput = destinationInput; } - /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ + /** + * Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on + * what header location is + */ @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - HttpRequest request = (HttpRequest) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, + false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } - ctx.channel().writeAndFlush(response); + ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response); } } From ad1ddaee10a9c41764c2f6f9ebc57097460d2907 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 237/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 2 +- .../google/registry/xjc/package-info.java | 2 +- prober/build.gradle | 5 - .../monitoring/blackbox/NewChannelAction.java | 136 ++++++++ .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProbingAction.java | 318 +++++------------- .../handlers/ServerSideException.java | 15 + .../handlers/SslClientInitializer.java | 20 +- .../handlers/WebWhoisActionHandler.java | 150 +++------ .../blackbox/messages/HttpRequestMessage.java | 67 +--- .../messages/HttpResponseMessage.java | 46 ++- .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 15 files changed, 346 insertions(+), 446 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/prober/build.gradle b/prober/build.gradle index 86d1bcb0051..c379ca78172 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -22,8 +22,6 @@ dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] @@ -35,9 +33,6 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..0ba3a0c22be --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index a4d78495826..333330207f1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,30 +14,17 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by - * Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** - * Main Dagger Component - */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() - .build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index cdb099e4a76..2441debb12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,278 +14,159 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; +import io.netty.util.AttributeKey; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; -import io.netty.util.AttributeKey; import io.netty.util.HashedWheelTimer; import io.netty.util.Timer; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import javax.inject.Provider; -import org.joda.time.Duration; /** - * AutoValue class that represents action generated by {@link ProbingStep} + *Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when - * the task has been completed

+ * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the + * task has been completed

* - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type - * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall - * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the - * details of that connection.

+ *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. + * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} + * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes - * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when - * informed that the connection is successful. If the channel is supplied, the connection future is - * automatically set to successful.

+ *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

*/ -@AutoValue + public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** - * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when - * channel is active. - */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey - .valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - /** - * {@link AttributeKey} in channel that gives the information of the channel's host. - */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey - .valueOf("REMOTE_ADDRESS_KEY"); /** - * {@link Timer} that rate limits probing - */ + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; + + + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; + } + + /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** - * Actual {@link Duration} of this delay - */ + + /** Actual {@link Duration} of this delay */ public abstract Duration delay(); - /** - * {@link OutboundMessageType} instance that we write and flush down pipeline to server - */ + /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ public abstract OutboundMessageType outboundMessage(); - /** - * {@link Channel} object that either created by or passed into this {@link ProbingAction} - * instance - */ - @Nullable + /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** - * The {@link Protocol} instance that specifies type of connection - */ + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); - /** - * The hostname of the remote host we have a connection or will make a connection to - */ public abstract String host(); - /** - * Performs the work of the actual action - * - *

First, checks if channel is active by setting a listener to perform the bulk of the work - * when the connection future is successful.

- * - *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

- * - *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

- * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. - */ - - - /** - * Method that calls on {@code performAction} when it is certain channel connection is - * established. - */ - @Override - public ChannelFuture call() { - //ChannelPromise that we return - ChannelPromise finished = channel().newPromise(); - - //Ensures channel has been set up with connection future as an attribute - checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); - - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture connectionFuture) -> { - if (connectionFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - - ActionHandler actionHandler; - try { - actionHandler = channel().pipeline().get(ActionHandler.class); - } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw - // an UndeterminedStateException - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); - - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture unusedFutureWriteAndFlush = - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> { - if (future.isSuccess()) { - ChannelFuture unusedFuture = finished.setSuccess(); - } else { - ChannelFuture unusedFuture = finished.setFailure(future.cause()); - } - }, - //If we don't have a persistent connection, close the connection to this - // channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) { - logger.atInfo() - .log("Closed stale channel. Moving on to next ProbingStep"); - } else { - logger.atWarning() - .log( - "Could not close channel. Stale connection still exists" - + "."); - } - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(connectionFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> finished.setSuccess(), + future -> { + if (!protocol().persistentConnection()) { + + //If we created a new channel for this action, close the connection to the channel + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); } } ); - return finished; } - - /** - * {@link AutoValue.Builder} that does work of creating connection when not already present. + * The method that sends the {@code outboundMessage} down the channel pipeline + * + * @return future that denotes when the action has been successfully performed */ - @AutoValue.Builder - public abstract static class Builder { - private Bootstrap bootstrap; + @Override + public ChannelFuture call() { - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); } - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setHost(String value); - - public abstract Builder setChannel(Channel channel); + //ChannelPromise that we use to inform ProbingStep when we are finished. + ChannelPromise finished = channel().newPromise(); - abstract Protocol protocol(); + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } - abstract Channel channel(); + return finished; + } - abstract String host(); + public abstract static class Builder, P extends ProbingAction> { - abstract ProbingAction autoBuild(); + public abstract B delay(Duration value); - public ProbingAction build() { - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - address = new LocalAddress(host()); - } + public abstract B outboundMessage(OutboundMessageType value); - checkArgument(channel() == null ^ bootstrap == null, - "One and only one of bootstrap and channel must be supplied."); - //If a channel is supplied, nothing is needed to be done + public abstract B protocol(Protocol value); - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel() == null) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); + public abstract B host(String value); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); + public abstract B path(String value); - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } + public abstract P build(); - //now we can actually build the ProbingAction - return autoBuild(); - } - } - - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); } /** @@ -295,26 +176,11 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - private static void addHandlers( + static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { channelPipeline.addLast(handlerProvider.get()); } } - - - @Override - public final String toString() { - return String.format( - "ProbingAction with delay: %d\n" - + "outboundMessage: %s\n" - + "protocol: %s\n" - + "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index c62668b19b2..ac844ac99df 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,11 +15,12 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; + +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler.Sharable; @@ -63,8 +64,7 @@ public SslClientInitializer(SslProvider sslProvider) { this(sslProvider, null, null, null); } - public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, - Supplier certificateSupplier) { + public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, Supplier certificateSupplier) { //We use the default trust store here as well, setting trustCertificates to null this(sslProvider, null, privateKeySupplier, certificateSupplier); } @@ -89,8 +89,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - String host = channel.attr(REMOTE_ADDRESS_KEY).get(); + ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); + Protocol protocol = action.protocol(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -98,14 +98,12 @@ protected void initChannel(C channel) throws Exception { SslContextBuilder.forClient() .sslProvider(sslProvider) .trustManager(trustedCertificates); - if (privateKeySupplier != null && certificateSupplier != null) { - sslContextBuilder = sslContextBuilder - .keyManager(privateKeySupplier.get(), certificateSupplier.get()); - } + if (privateKeySupplier != null && certificateSupplier != null) + sslContextBuilder = sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get()); SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), host, protocol.port()); + .newHandler(channel.alloc(), action.host(), protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index c0f7ce8ae78..21010f0e887 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,21 +14,24 @@ package google.registry.monitoring.blackbox.handlers; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; + import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -36,72 +39,39 @@ import org.joda.time.Duration; /** - * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response - * implies a redirection it follows the redirection until either an Error Response is received, or - * {@link HttpResponseStatus.OK} is received

+ *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection + * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

*/ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** - * {@link Bootstrap} necessary for remaking connection on redirect response. - */ - private final Bootstrap bootstrap; - - /** - * {@link Protocol} for when redirected to http endpoint. - */ - private final Protocol httpWhoisProtocol; - - /** - * {@link Protocol} for when redirected to https endpoint. - */ - private final Protocol httpsWhoisProtocol; - - /** - * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. - */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } + public WebWhoisActionHandler() {} /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, - * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a - * response indicating a Failure, or receives a redirection response, where it follows the - * redirects until receiving one of the previous three responses. + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { + throws ServerSideException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status().equals(HttpResponseStatus.OK)) { + + if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - //On success, we always pass message to ActionHandler's channelRead0 method. - super.channelRead0(ctx, msg); + finished.setSuccess(); + + logger.atInfo().log("Response Received: " + response); - } else if (response.headers().get("location") != null) { + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { //Obtain url to be redirected to URL url; @@ -109,75 +79,55 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException( - "Redirected Location was invalid. Given Location was: " + response.headers() - .get("Location")); + throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); + int newPort = url.getDefaultPort(); - logger.atInfo().log(String - .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, - url.getDefaultPort(), newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException( - "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); - } + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); + + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) .build(); + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } - - //Once channel is closed, establish new connection to redirected host, and repeat - // same actions + logger.atInfo().log("Successfully Closed Connection"); + + //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell - // ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE + finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 745a360cab5..3fb8c187ad9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -19,30 +5,19 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; -/** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. - * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a {@code - * name} method, which returns a standard name and the current hostname.

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, - ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + @Override @@ -51,35 +26,15 @@ public HttpRequestMessage setUri(String path) { return this; } - /** - * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} - */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } - - /** - * Modifies headers to reflect new host and new path if applicable. - */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) { - setUri(args[1]); - } - - return this; + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + ByteBuf buf = request.content(); + if (buf == null) { + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - } - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 7d2ff722076..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,21 +6,33 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} - */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { + super(version, status); + } + + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } - /** - * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} - */ - public HttpResponseMessage(FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); + + return finalResponse; } + + + } diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From 2f68f4fcbde5e1cf3489f64a6827fdbd7303b56b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:58:52 -0400 Subject: [PATCH 238/337] Fixed changes suggested by CydeWeys --- prober/build.gradle | 10 +- .../monitoring/blackbox/Protocol.java | 96 +++++--- .../blackbox/exceptions/FailureException.java | 15 +- .../blackbox/handlers/ActionHandler.java | 104 +++----- .../blackbox/messages/InboundMessageType.java | 10 +- .../handlers/WebWhoisActionHandlerTest.java | 232 ++++++++---------- 6 files changed, 219 insertions(+), 248 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index c379ca78172..ae4bd27b731 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -17,11 +17,12 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - dependencies { def deps = rootProject.dependencyMap - + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] @@ -33,16 +34,17 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - + testCompile deps['com.google.truth:truth'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index e524e787742..05af501ad5a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,63 +16,97 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; import javax.inject.Provider; /** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. + * Protocol Class packages all static variables necessary for a certain type of connection + * Both the host and the path can be changed for the same protocol + * Mainly packages the handlers necessary for the requisite channel pipeline */ @AutoValue public abstract class Protocol { + public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + /** - * {@link AttributeKey} that lets channel reference {@link Protocol} that created it. + * Default names associated with each protocol */ - public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + final static String EPP_PROTOCOL_NAME = "EPP"; + final static String DNS_PROTOCOL_NAME = "DNS"; + final static String WHOIS_PROTOCOL_NAME = "WHOIS"; + final static String RDAP_PROTOCOL_NAME = "RDAP"; + + private String host; + private String path = ""; + private ProbingAction probingAction; + + /** Setter method for Protocol's host*/ + public Protocol host(String host) { + this.host = host; + return this; + } + + /** Getter method for Protocol's host*/ + public String host() { + return host; + } + + /** Setter method for Protocol's path*/ + public Protocol path(String path) { + this.path = path; + return this; + } + + /** Getter method for Protocol's path*/ + public String path() { + return path; + } + + /** Setter method for Protocol's ProbingAction parent*/ + public Protocol probingAction(ProbingAction probingAction) { + this.probingAction = probingAction; + return this; + } + + /** Getter method for Protocol's path*/ + public ProbingAction probingAction() { + return probingAction; + } + + /** If connection associated with Protocol is persistent, which is only EPP */ + public boolean persistentConnection() { + return name() == EPP_PROTOCOL_NAME; + } + /** Protocol Name */ public abstract String name(); + /** Port to bind to at remote host */ public abstract int port(); - /** - * The {@link ChannelHandler} providers to use for the protocol, in order. - */ - abstract ImmutableList> handlerProviders(); + /** The {@link ChannelHandler} providers to use for the protocol, in order. */ + public abstract ImmutableList> handlerProviders(); - /** - * Boolean that notes if connection associated with Protocol is persistent. - */ - abstract boolean persistentConnection(); + + public abstract Builder toBuilder(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } - /** Default {@link AutoValue.Builder} for {@link Protocol}. */ - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder setName(String value); + @AutoValue.Builder + public static abstract class Builder { - public abstract Builder setPort(int num); + public abstract Builder name(String value); - public abstract Builder setHandlerProviders( - ImmutableList> providers); + public abstract Builder port(int num); - public abstract Builder setPersistentConnection(boolean value); + public abstract Builder handlerProviders(ImmutableList> providers); public abstract Protocol build(); } - - @Override - public String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); - } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 36687e7ac82..9f716bb2589 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,18 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.exceptions; +package google.registry.monitoring.blackbox; -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class FailureException extends Exception { - - public FailureException(String msg) { - super(msg); - } - - public FailureException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 6552bca3eca..3fa60cd844a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,99 +15,69 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; +import com.google.common.flogger.StackSize; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpResponse; +import java.util.function.Function; +import javax.inject.Inject; /** - * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline - * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType - * >}, as it should only be passed in messages that implement the {@link InboundMessageType} - * interface.

* - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a - * {@link - * ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this - * channel is informed of the error. If the error is an instance of a {@link FailureException} - * {@code finished} is marked as a failure with cause {@link FailureException}. If it is any other - * type of error, it is treated as an {@link UndeterminedStateException} and {@code finished} set as - * a failure with the same cause as what caused the exception. Lastly, if no error is thrown, we - * know the action completed as a success, and, as such, we mark {@code finished} as a success.

- * - *

Subclasses specify further work to be done for specific kinds of channel pipelines.

+ * @param Generic Type of Inbound Message + * @param Generic Type of Outbound Message + * Abstract class that tells sends message down pipeline and + * and tells listeners to move on when the message is received. */ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +public abstract class ActionHandler extends SimpleChannelInboundHandler + implements Function { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** - * {@link ChannelPromise} that informs {@link ProbingAction} if response has been received. - */ - private ChannelPromise finished; + protected ChannelPromise finished; + private Channel channel; + - /** - * Returns initialized {@link ChannelPromise} to {@link ProbingAction}. + /** returns ChannelPromise for when inbound message is recieved + * a + * @param outboundMessage + * @return */ - public ChannelFuture getFinishedFuture() { + @Override + public ChannelFuture apply(O outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + + channel.writeAndFlush(outboundMessage); return finished; + + } + + public void resetFuture() { + finished = channel.newPromise(); } - /** - * Initializes {@link ChannelPromise} - */ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler + + channel = ctx.channel(); finished = ctx.newPromise(); } - /** - * Marks {@link ChannelPromise} as success - */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ + //Only purpose of Handler is to mark future as a success - ChannelFuture unusedFuture = finished.setSuccess(); + finished.setSuccess(); } - /** - * Logs the channel and pipeline that caused error, closes channel, then informs {@link - * ProbingAction} listeners of error. - */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atWarning().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); - - if (cause instanceof FailureException) { - //On FailureException, we know the response is a failure. - - //Since it wasn't a success, we still want to log to see what caused the FAILURE - logger.atInfo().log(cause.getMessage()); - - //As always, inform the ProbingStep that we successfully completed this action - ChannelFuture unusedFuture = finished.setFailure(cause); - - } else { - //On UndeterminedStateException, we know the response type is an error. - - //Since it wasn't a success, we still log what caused the ERROR - logger.atWarning().log(cause.getMessage()); - ChannelFuture unusedFuture = finished.setFailure(cause); - - //As this was an ERROR in performing the action, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } + logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 0a584dfa2a7..cb9c96f37f6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -12,12 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.messages; - -/** - * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in - * channel pipeline - */ -public interface InboundMessageType { - -} +package google.registry.monitoring.blackbox; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 5a0d0908724..63bb2cf5b53 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,221 +15,207 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelPromise; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import javax.inject.Provider; +import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@link WebWhoisActionHandler}. - * - *

Attempts to test how well {@link WebWhoisActionHandler} works - * when responding to all possible types of responses

- */ +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; + private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; + private static final String HTTPS_REDIRECT = "https://"; + private static final String REDIRECT_HOST = "www.example.com"; + private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; - private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private final Protocol standardProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( - null, null, null, null))) - .setName("http") - .setPersistentConnection(false) - .setPort(HTTP_PORT) - .build(); + private static final Duration DEFAULT_DURATION = new Duration(0L); private EmbeddedChannel channel; private ActionHandler actionHandler; - private Provider actionHandlerProvider; - private Protocol initialProtocol; - private HttpRequestMessage msg; - - /** - * Creates default protocol with empty list of handlers and specified other inputs - */ - private Protocol createProtocol(String name, int port, boolean persistentConnection) { + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() - .setName(name) - .setPort(port) - .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) - .setPersistentConnection(persistentConnection) - .build(); + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); } - /** - * Initializes new WebWhoisActionHandler - */ - private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { - actionHandler = new WebWhoisActionHandler( - bootstrap, - standardProtocol, - standardProtocol, - messageTemplate - ); - actionHandlerProvider = () -> actionHandler; + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); } - /** - * Sets up testing channel with requisite attributes - */ + /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol) { + setupActionHandler(); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - private Bootstrap makeBootstrap(EventLoopGroup group) { - return new Bootstrap() - .group(group) - .channel(LocalChannel.class); + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group, LocalAddress address) { - WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); } - private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { - msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); - setupActionHandler(bootstrap, msg); - initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; } + @Test - public void testBasic_responseOk() { + public void testSuccess_responseOk() { //setup - setup("", null, true); + Protocol initialProtocol = createProtocol("responseOk", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); - //assesses that we successfully received good response and protocol is unchanged + //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badRequest() { + public void testSuccess_responseBad() { //setup - setup("", null, false); + Protocol initialProtocol = createProtocol("responseBad", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage( - makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(future.isDone()).isTrue(); + assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } - @SuppressWarnings("CheckReturnValue") @Test - public void testBasic_responseFailure_badURL() { + public void testSuccess_redirectCloseChannel() { //setup - setup("", null, false); - setupChannel(initialProtocol); + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, and event is success - assertThat(future.isDone()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_redirect() { - // Sets up EventLoopGroup with 1 thread to be blocking. - EventLoopGroup group = new NioEventLoopGroup(1); - - // Sets up embedded channel. - setup("", makeBootstrap(group), false); - setupChannel(initialProtocol); - - // Initializes LocalAddress with unique String. - String host = TARGET_HOST + System.currentTimeMillis(); - LocalAddress address = new LocalAddress(host); + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group, address); - FullHttpResponse response = - new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + host, true, false)); + channel.writeInbound(originalResponse); - //checks that future has not been set to successful or a failure - assertThat(future.isDone()).isFalse(); + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); - channel.writeInbound(response); + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } + } From 485096b360d919692e37cfa4d3d5575227a31550 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 239/337] Added missing license headers and JavaDoc --- .../handlers/ServerSideException.java | 16 ++++++- .../blackbox/messages/HttpRequestMessage.java | 45 ++++++++++++++----- .../messages/HttpResponseMessage.java | 32 ++++++++++--- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java index 5d3addb920e..441062a9e7b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; /** @@ -12,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 3fb8c187ad9..8fbb55c6339 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,13 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} + * (but needs to implement {@link OutboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion + * from {@link FullHttpRequest} to its type

+ */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +35,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,15 +42,22 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - if (buf == null) { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //creates message based on content found in original request + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //stores headers from request in finalRequest + request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); + + return finalRequest; + + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..776e7de0824 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,11 +1,33 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} + * (but needs to implement {@link InboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion + * from {@link FullHttpResponse} to its type

+ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -17,22 +39,20 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } + /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); + //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + //stores headers from response in finalResponse + response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); return finalResponse; } - - - } From 711ef15a8b738b5ae77f42221ab3414277220afb Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 240/337] Minor fix in NewChannelAction JavaDoc --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..1e7578d5679 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; - import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -28,8 +27,7 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) */ @AutoValue public abstract class NewChannelAction extends ProbingAction { From 4ba5ed812c2c2106d6c59076443629c1a406098d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 13:33:23 -0400 Subject: [PATCH 241/337] Minor Style Fix --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 ---- .../java/google/registry/monitoring/blackbox/Protocol.java | 1 - .../registry/monitoring/blackbox/handlers/ActionHandler.java | 1 - .../monitoring/blackbox/handlers/WebWhoisActionHandler.java | 2 -- 4 files changed, 8 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..84cf75492f2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -52,7 +52,6 @@ public Channel channel() { return this.channel; } - @Override public abstract Builder toBuilder(); @@ -120,7 +119,6 @@ public static NewChannelAction.Builder builder() return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -129,6 +127,4 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 05af501ad5a..22f3d27c08b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -109,4 +109,3 @@ public static abstract class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 3fa60cd844a..503d211b324 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -80,4 +80,3 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 21010f0e887..5b77461cd8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -131,7 +131,5 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } } - - } From 05f676c727645ce0ab2cc3926c7ae0d518a85243 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 242/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 10 +- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 17 +- .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProberModule.java | 97 ++++--- .../monitoring/blackbox/ProbingAction.java | 17 +- .../monitoring/blackbox/ProbingSequence.java | 122 +++++---- .../monitoring/blackbox/ProbingStep.java | 200 ++++++-------- .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 12 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 ++++ .../monitoring/blackbox/WebWhoisModule.java | 216 ++++++--------- .../exceptions/EppClientException.java | 29 ++ .../exceptions/InternalException.java | 29 ++ .../exceptions/ResponseException.java | 29 ++ .../ServerSideException.java | 4 +- .../blackbox/handlers/ActionHandler.java | 88 ++++--- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/WebWhoisActionHandler.java | 19 +- .../handlers/WebWhoisMessageHandler.java | 42 +-- .../blackbox/messages/HttpRequestMessage.java | 50 +--- .../messages/HttpResponseMessage.java | 32 +-- .../blackbox/messages/InboundMessageType.java | 8 +- .../messages/OutboundMessageType.java | 20 +- .../blackbox/ProbingActionTest.java | 173 ++++++------ .../blackbox/TestServers/TestServer.java | 85 ++++++ .../blackbox/TestServers/WebWhoisServer.java | 92 +++++++ .../monitoring/blackbox/TestUtils.java | 172 ++++++++++-- .../monitoring/blackbox/TokenTest.java | 19 +- .../blackbox/handlers/ConversionHandler.java | 23 +- .../blackbox/handlers/NettyRule.java | 95 ++----- .../handlers/SslClientInitializerTest.java | 73 ++++-- .../blackbox/handlers/TestActionHandler.java | 12 +- .../handlers/WebWhoisActionHandlerTest.java | 247 +++++++++++++----- 36 files changed, 1466 insertions(+), 827 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java diff --git a/prober/build.gradle b/prober/build.gradle index ae4bd27b731..b23314728e1 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -17,9 +17,10 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - + compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] compile deps['com.google.code.gson:gson'] @@ -40,11 +41,12 @@ dependencies { runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - + testCompile deps['com.google.truth:truth'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') + //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -54,3 +56,7 @@ dependencies { testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } +task(runMain, dependsOn: 'classes', type: JavaExec) { + main = 'google.registry.monitoring.blackbox.Prober' + classpath = sourceSets.main.runtimeClasspath +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 84cf75492f2..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -52,6 +53,7 @@ public Channel channel() { return this.channel; } + @Override public abstract Builder toBuilder(); @@ -83,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -116,9 +118,10 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } + @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -127,4 +130,6 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } + } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 333330207f1..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,16 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index bf9b93d6913..73bd9127852 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,86 +14,99 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SslProvider; import java.util.Set; import javax.inject.Singleton; -import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and - * stores {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link - * ProbingSequence}. + * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} + * + *

Provides

*/ @Module public class ProberModule { + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; - /** - * Default {@link Duration} chosen to be time between each {@link ProbingAction} call. - */ - private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - - /** - * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. - */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** - * {@link Provides} one global {@link Channel} class that is used to construct a {@link - * io.netty.bootstrap.Bootstrap}. - */ @Provides - @Singleton - Class provideChannelClass() { - return NioSocketChannel.class; + @HttpWhoisProtocol + ProbingSequence provideHttpWhoisSequence( + @HttpWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** - * {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. - */ @Provides - @Singleton - Duration provideDuration() { - return DEFAULT_DURATION; + @HttpsWhoisProtocol + ProbingSequence provideHttpsWhoisSequence( + @HttpsWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** - * {@link Provides} the {@link SslProvider} used by instances of {@link - * google.registry.monitoring.blackbox.handlers.SslClientInitializer} - */ @Provides - @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } - /** - * Root level {@link Component} that provides each {@link ProbingSequence}. - */ + @Provides + @HttpsWhoisProtocol + int provideHttpsWhoisPort() { + return httpsWhoIsPort; + } + + @Provides + ImmutableMap providePortToProtocolMap( + Set protocolSet) { + return Maps.uniqueIndex(protocolSet, Protocol::port); + } + + + @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, + TokenModule.class }) public interface ProberComponent { - //Standard WebWhois sequence - Set provideAllSequences(); + @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); + + @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); + + ImmutableMap providePortToProtocolMap(); + + @WebWhoisProtocol Token provideWebWhoisToken(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2441debb12d..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -34,7 +34,7 @@ import javax.inject.Provider; /** - *Superclass that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -183,4 +183,19 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + @Override + public String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n" + + "path: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host(), + path() + ); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 175cf4dcfa5..6387207fea4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,95 +14,109 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. + * Represents Sequence of {@link ProbingSteps} that the Prober performs in order * + * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} + * but for tests is {@link LocalChannel} * - *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} - * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one - * is the first repeated step.

+ *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, + * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

* - *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once - * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest - * of the work.

+ *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one + * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

*/ -public class ProbingSequence { +public class ProbingSequence { + private ProbingStep firstStep; - private ProbingStep firstStep; + /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ + private EventLoopGroup eventGroup; - /** - * Each {@link ProbingSequence} requires a start token to begin running. - */ - private Token startToken; + /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ + private Bootstrap bootstrap; + + public Bootstrap getBootstrap() { + return bootstrap; + } - public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + public void start(Token token) { + // calls the first step with input token; + firstStep.accept(token); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link - * Bootstrap}. + * {@link Builder} which takes in {@link ProbingStep}s + * + * @param Same specified {@code C} for overall {@link ProbingSequence} */ - public static class Builder { - - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - - private Token startToken; - - public Builder(Token startToken) { - this.startToken = startToken; + public static class Builder { + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstSequenceStep; + private EventLoopGroup eventLoopGroup; + private Class classType; + + Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; + return this; } - /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, built, and pointed to by - * the previous {@link ProbingStep} added. - */ - public Builder addStep(ProbingStep step) { - + Builder addStep(ProbingStep step) { if (currentStep == null) { firstStep = step; } else { currentStep.nextStep(step); } - currentStep = step; return this; } - /** - * We take special note of the first repeated step. - */ - public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; + /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ + Builder makeFirstRepeated() { + firstSequenceStep = currentStep; + return this; + } + /** Set the class to be the same as {@code C} */ + public Builder setClass(Class classType) { + this.classType = classType; return this; } - /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private - * constructor to create {@link ProbingSequence}. - */ - public ProbingSequence build() { - if (firstRepeatedStep == null) { - firstRepeatedStep = firstStep; - } - - currentStep.nextStep(firstRepeatedStep); + public ProbingSequence build() { + currentStep.nextStep(firstSequenceStep); currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); } + } - private ProbingSequence(ProbingStep firstStep, Token startToken) { + /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ + private void setParents() { + ProbingStep currentStep = firstStep.parent(this).nextStep(); + + while (currentStep != firstStep) { + currentStep = currentStep.parent(this).nextStep(); + } + } + private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, + Class classType) { this.firstStep = firstStep; - this.startToken = startToken; + this.eventGroup = eventLoopGroup; + this.bootstrap = new Bootstrap() + .group(eventGroup) + .channel(classType); + setParents(); + } + + @Override + public String toString() { + return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 98867c01220..5bad5abf6bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,181 +14,155 @@ package google.registry.monitoring.blackbox; -import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.io.IOException; import java.util.function.Consumer; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step in {@link - * ProbingSequence}. + * Represents generator of actions performed at each step in {@link ProbingSequence} + * + * @param See {@code C} in {@link ProbingSequence} * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} - * instances. It then modifies these components on each loop iteration with the consumed {@link - * Token} and from that, generates a new {@link ProbingAction} to call.

+ * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies + * these components on each loop iteration with the consumed {@link Token} and from that, + * generates new {@link ProbingAction} to perform<./p> + * + *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -@AutoValue -public abstract class ProbingStep implements Consumer { +public abstract class ProbingStep implements Consumer { + public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); + protected static final Duration DEFAULT_DURATION = new Duration(2000L); private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** - * Necessary boolean to inform when to obtain next {@link Token} - */ - protected boolean isLastStep = false; - private ProbingStep nextStep; - - /** - * Time delay duration between actions. - */ - abstract Duration duration(); - - /** - * {@link Protocol} type for this step. - */ - abstract Protocol protocol(); - - /** - * {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. - */ - abstract OutboundMessageType messageTemplate(); - - /** - * {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation - * of new channels. - */ - abstract Bootstrap bootstrap(); - + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + protected LocalAddress address = DEFAULT_ADDRESS; - /** Default {@link AutoValue.Builder} for {@link ProbingStep}. */ - @AutoValue.Builder - public abstract static class Builder { + /** Necessary boolean to inform when to obtain next {@link Token}*/ + private boolean isLastStep = false; + private ProbingStep nextStep; + private ProbingSequence parent; - public abstract Builder setDuration(Duration value); + protected Duration duration; - public abstract Builder setProtocol(Protocol value); + protected final Protocol protocol; + protected final OutboundMessageType message; - public abstract Builder setMessageTemplate(OutboundMessageType value); - - public abstract Builder setBootstrap(Bootstrap value); + protected ProbingStep(Protocol protocol, OutboundMessageType message) { + this.protocol = protocol; + this.message = message; + } - public abstract ProbingStep build(); + private OutboundMessageType message() { + return message; } - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); + Protocol protocol() { + return protocol; } + void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - /** - * Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} - */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { - OutboundMessageType message = token.modifyMessage(messageTemplate()); - ProbingAction.Builder probingActionBuilder = ProbingAction.builder() - .setDelay(duration()) - .setProtocol(protocol()) - .setOutboundMessage(message) - .setHost(token.host()); - - if (token.channel() != null) { - probingActionBuilder.setChannel(token.channel()); + ProbingStep parent(ProbingSequence parent) { + this.parent = parent; + return this; + } + + /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + private ProbingAction generateAction(Token token) throws InternalException { + ProbingAction generatedAction; + + OutboundMessageType message = token.modifyMessage(message()); + + //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction + if (protocol().persistentConnection() && token.channel() != null) { + generatedAction = ExistingChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .channel(token.channel()) + .build(); } else { - probingActionBuilder.setBootstrap(bootstrap()); - } + generatedAction = NewChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .bootstrap(parent.getBootstrap()) + .address(address) + .build(); - return probingActionBuilder.build(); + } + return generatedAction; } - /** - * On the last step, gets the next {@link Token}. Otherwise, uses the same one. - */ + /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ private Token generateNextToken(Token token) { - return isLastStep ? token.next() : token; + return (isLastStep) ? token.next() : token; } - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the - * action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is completed is - * marked as a success, we note a success. Otherwise, if the cause of failure will either be a - * failure or error.

- */ @Override public void accept(Token token) { - ProbingAction currentAction; + ProbingAction nextAction; //attempt to generate new action. On error, move on to next step try { - currentAction = generateAction(token); - } catch (UndeterminedStateException e) { + nextAction = generateAction(token); + } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch (Exception e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; + //If the next step maintains the connection, pass on the channel from this + if (protocol().persistentConnection()) { + token.channel(nextAction.channel()); } + //call the created action + ChannelFuture future = nextAction.call(); + + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - + nextStep.accept(generateNextToken(token)); } else { - //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - - if (protocol().persistentConnection()) { - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - } - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - }); } @Override - public final String toString() { - return String.format("ProbingStep with Protocol: %s\n" - + "OutboundMessage: %s\n", + public String toString() { + return String.format("ProbingStep with Protocol: %s\n" + + "OutboundMessage: %s\n" + + "and parent sequence: %s", protocol(), - messageTemplate().getClass().getName()); + message(), + parent); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 22f3d27c08b..06ce0532da0 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -108,4 +108,16 @@ public static abstract class Builder { public abstract Protocol build(); } + + @Override + public String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 55fc7cf71a9..dba905c0e49 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,120 +18,90 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; + +import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.time.Duration; -/** - * A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. - */ +/** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; - private static final String HTTP_PROTOCOL_NAME = "http"; - private static final String HTTPS_PROTOCOL_NAME = "https"; - - /** - * Standard length of messages used by Proxy. Equates to 0.5 MB. - */ - private static final int maximumMessageLengthBytes = 512 * 1024; + final static String DOMAIN_SUFFIX = "whois.nic."; - /** - * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. - */ + /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpWhoisProtocol { + @interface HttpWhoisProtocol {} - } + /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ + @Qualifier + @interface HttpsWhoisProtocol {} - /** - * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. - */ + /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier - public @interface HttpsWhoisProtocol { + public @interface WebWhoisProtocol {} - } - /** - * Dagger qualifier to provide any WebWhois related bindings. - */ - @Qualifier - public @interface WebWhoisProtocol { - } + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + - /** - * {@link Provides} standard WebWhois sequence. - */ @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { + @HttpWhoisProtocol + static ProbingStep provideHttpWhoisProbingSequence( + @HttpWhoisProtocol Protocol httpWhoisProtocol) { + return new ProbingStepWeb<>(httpWhoisProtocol); + } - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); + @Provides + @HttpsWhoisProtocol + static ProbingStep provideHttpsWhoisProbingStep( + @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { + return new ProbingStepWeb<>(httpsWhoisProtocol); } - /** - * {@link Provides} only step used in WebWhois sequence. - */ + @Singleton @Provides - @WebWhoisProtocol - static ProbingStep provideWebWhoisStep( - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @WebWhoisProtocol Bootstrap bootstrap, - HttpRequestMessage messageTemplate, - Duration duration) { - - return ProbingStep.builder() - .setProtocol(httpWhoisProtocol) - .setBootstrap(bootstrap) - .setMessageTemplate(messageTemplate) - .setDuration(duration) + @HttpWhoisProtocol + static Protocol provideHttpWhoisProtocol( + @HttpWhoisProtocol int httpWhoisPort, + @HttpWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** - * {@link Provides} the {@link Protocol} that corresponds to http connection. - */ @Singleton @Provides - @HttpWhoisProtocol - static Protocol provideHttpWhoisProtocol( + @IntoSet + static Protocol provideHttpProtocolForSet( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTP_PROTOCOL_NAME) - .setPort(httpWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** - * {@link Provides} the {@link Protocol} that corresponds to https connection. - */ + @Singleton @Provides @HttpsWhoisProtocol @@ -139,24 +109,40 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTPS_PROTOCOL_NAME) - .setPort(httpsWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } + @Singleton + @Provides + @IntoSet + static Protocol provideHttpsProtocolForSet( + @HttpsWhoisProtocol int httpsWhoisPort, + @HttpsWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Provides + @WebWhoisProtocol + String provideHttpWhoisHost() { + return "app"; + } + - /** - * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http - * protocol. - */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -165,18 +151,13 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** - * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https - * protocol. - */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( - @HttpsWhoisProtocol - Provider> sslClientInitializerProvider, + @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -186,67 +167,34 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } - @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); - } - - @Provides - static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { - return new HttpObjectAggregator(maxContentLength); - } - - /** - * {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. - */ - @Provides - @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer( - SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); - } - /** - * {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. - */ - @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap( - EventLoopGroup eventLoopGroup, - Class channelClazz) { - return new Bootstrap() - .group(eventLoopGroup) - .channel(channelClazz); + static MessageHandler provideMessageHandler() { + return new WebWhoisMessageHandler(); } @Provides - @WebWhoisProtocol - int provideMaximumMessageLengthBytes() { - return maximumMessageLengthBytes; + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); } - /** - * {@link Provides} the list of top level domains to be probed - */ - @Singleton @Provides - @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy", "xn--q9jyb4c"); + static HttpObjectAggregator provideHttpObjectAggregator() { + return new HttpObjectAggregator(1048576); } @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return HTTP_WHOIS_PORT; + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } @Provides @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return HTTPS_WHOIS_PORT; + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 503d211b324..7898203e92d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,68 +15,88 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import com.google.common.flogger.StackSize; -import io.netty.channel.ChannelInboundHandlerAdapter; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpResponse; -import java.util.function.Function; -import javax.inject.Inject; /** + *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - * @param Generic Type of Inbound Message - * @param Generic Type of Outbound Message - * Abstract class that tells sends message down pipeline and - * and tells listeners to move on when the message is received. + *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

+ * + *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} + * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception + * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses + * specify further work to be done for specific kinds of channel pipelines.

*/ -public abstract class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - protected ChannelPromise finished; - private Channel channel; + /** Three types of responses received down pipeline */ + public enum ResponseType {SUCCESS, FAILURE, ERROR} + /** Status of response for current {@link ActionHandler} instance */ + private static ResponseType status; - /** returns ChannelPromise for when inbound message is recieved - * a - * @param outboundMessage - * @return - */ - @Override - public ChannelFuture apply(O outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline + protected ChannelPromise finished; - channel.writeAndFlush(outboundMessage); + /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + public ChannelFuture getFuture() { return finished; - - } - - public void resetFuture() { - finished = channel.newPromise(); } + /** Initializes new {@link ChannelPromise} */ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler - - channel = ctx.channel(); finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ - //Only purpose of Handler is to mark future as a success - + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + //simply marks finished as success + status = ResponseType.SUCCESS; finished.setSuccess(); } + /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); + logger.atSevere().withCause(cause).log(String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), + ctx.channel().pipeline().toString())); + + + if (ResponseException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + status = ResponseType.FAILURE; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (ServerSideException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + status = ResponseType.ERROR; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (InternalException.class.isInstance(cause)){ + logger.atSevere().withCause(cause).log("Severe internal error"); + finished.setFailure(cause); + } else { + finished.setFailure(cause); + } + + //due to failure, close channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 5b77461cd8f..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -17,20 +17,16 @@ import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; @@ -59,7 +55,7 @@ public WebWhoisActionHandler() {} */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ServerSideException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -67,9 +63,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - finished.setSuccess(); - logger.atInfo().log("Response Received: " + response); + super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -79,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -126,10 +121,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + throw new ResponseException("Response received from remote site was: " + response.status()); } } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 576d6a04d42..4afc5d95ba7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,59 +1,33 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -/** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom - * type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for - * redirection. - */ -public class WebWhoisMessageHandler extends ChannelDuplexHandler { +public class WebWhoisMessageHandler extends MessageHandler { + + private HttpRequestMessage request; @Inject - public WebWhoisMessageHandler() { - } + public WebWhoisMessageHandler() {} - /** - * Retains {@link HttpRequestMessage} and calls super write method. - */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) - throws Exception { - HttpRequestMessage request = (HttpRequestMessage) msg; + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** - * Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link - * InboundMessageType} instance. - */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + FullHttpResponse originalResponse = (FullHttpResponse) msg; - HttpResponseMessage response = new HttpResponseMessage(originalResponse); + InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8fbb55c6339..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,13 +6,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} - * (but needs to implement {@link OutboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion - * from {@link FullHttpRequest} to its type

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -35,6 +14,11 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + + @Override public HttpRequestMessage setUri(String path) { @@ -42,22 +26,16 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - - //creates message based on content found in original request - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - - - //stores headers from request in finalRequest - request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - - return finalRequest; - + HttpRequestMessage output; + if (buf == null) { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + } else { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + } + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 776e7de0824..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,33 +1,11 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} - * (but needs to implement {@link InboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion - * from {@link FullHttpResponse} to its type

- */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -39,20 +17,22 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } - /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); - //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - //stores headers from response in finalResponse - response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); return finalResponse; } + + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index cb9c96f37f6..0c1260becf2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -12,4 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.messages; + +/** + * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline + */ +public interface InboundMessageType {} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 4a7c16243cd..0dd17e9d4a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,24 +14,8 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; - /** - * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in - * channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType { - - /** - * All {@link OutboundMessageType} implementing classes should be able to be modified by token - * with String arguments - */ - OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; +public interface OutboundMessageType {} - /** - * Necessary to inform metrics collector what kind of message is sent down {@link - * io.netty.channel.ChannelPipeline} - */ - @Override - String toString(); -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index 6cfb235d97c..cbcf2fc82b0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,19 +15,20 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -38,85 +39,111 @@ import io.netty.channel.nio.NioEventLoopGroup; import javax.inject.Provider; import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; - /** * Unit tests for {@link ProbingAction} subtypes * *

Attempts to test how well each {@link ProbingAction} works with an {@link ActionHandler} * subtype when receiving to all possible types of responses

- */ + * */ @RunWith(JUnit4.class) public class ProbingActionTest { - - private static final String TEST_MESSAGE = "MESSAGE_TEST"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final int TEST_PORT = 0; - - private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - - /** - * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on - * {@link ProbingAction} - */ + /** Necessary Constants for test */ + private final String TEST_MESSAGE = "MESSAGE_TEST"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final int TEST_PORT = 0; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = () -> testHandler; - private Provider conversionHandlerProvider = () -> conversionHandler; + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - /** - * Used for testing how well probing step can create connection to blackbox server - */ + private ProbingAction newChannelAction; + private ProbingAction existingChannelAction; + private EmbeddedChannel channel; + private Protocol protocol; + + /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); + /** Sets up a {@link Protocol} corresponding to when a new connection is created */ + private void setupNewChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(false) + .build(); + } + /** Sets up a {@link Protocol} corresponding to when a new connection exists */ + private void setupExistingChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(true) + .build(); + } + + /** Sets up a {@link NewChannelAction} with test specified attributes */ + private void setupNewChannelAction() { + newChannelAction = NewChannelAction.builder() + .bootstrap(bootstrap) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .address(address) + .build(); + } + + private void setupChannel() { + channel = new EmbeddedChannel(); + } + + /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + private void setupExistingChannelAction(Channel channel) { + existingChannelAction = ExistingChannelAction.builder() + .channel(channel) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .build(); + } - @Ignore @Test public void testBehavior_existingChannel() { //setup - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up a Protocol corresponding to when a connection exists. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(true) - .build(); + setupChannel(); + setupExistingChannelProtocol(); + setupExistingChannelAction(channel); + channel.pipeline().addLast(conversionHandler); + channel.pipeline().addLast(testHandler); - // Sets up a ProbingAction that creates a channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setChannel(channel) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost("") - .build(); - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = existingChannelAction.call(); - //Obtains the outboundMessage passed through pipeline after delay - Object msg = null; - while (msg == null) { - msg = channel.readOutbound(); - } - //tests the passed message is exactly what we expect + //Ensures that we pass in the right message to the channel and haven't marked the future as success yet + Object msg = channel.readOutbound(); assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - assertThat(request).isEqualTo(TEST_MESSAGE); - - // Ensures that we haven't marked future as done until response is received. - assertThat(future.isDone()).isFalse(); + String response = ((ByteBuf) msg).toString(UTF_8); + assertThat(response).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()).isFalse(); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); @@ -128,41 +155,19 @@ public void testBehavior_existingChannel() { @Test public void testSuccess_newChannel() throws Exception { //setup - - LocalAddress address = new LocalAddress(ADDRESS_NAME); - Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); - - // Sets up a Protocol corresponding to when a new connection is created. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - + setupNewChannelProtocol(); + setupNewChannelAction(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - // Sets up a ProbingAction with existing channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future = future.syncUninterruptibly(); + future.sync(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler) testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()); + assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java new file mode 100644 index 00000000000..67e2cb7165d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -0,0 +1,85 @@ +package google.registry.monitoring.blackbox.TestServers; + +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; + +/** + * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + */ +public abstract class TestServer { + private LocalAddress localAddress; + + TestServer(LocalAddress localAddress, ImmutableList handlers) { + this(new NioEventLoopGroup(1), localAddress, handlers); + } + + TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + this.localAddress = localAddress; + + //Creates ChannelInitializer with handlers specified + ChannelInitializer serverInitializer = new ChannelInitializer() { + @Override + protected void initChannel(LocalChannel ch) { + for (ChannelHandler handler : handlers) { + ch.pipeline().addLast(handler); + } + } + }; + //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using LocalServerChannel class + ServerBootstrap serverBootstrap = + new ServerBootstrap() + .group(eventLoopGroup) + .channel(LocalServerChannel.class) + .childHandler(serverInitializer); + + ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); + + } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** Saves any inbound error as the cause of the promise failure. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java new file mode 100644 index 00000000000..ab9997b6c68 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -0,0 +1,92 @@ +package google.registry.monitoring.blackbox.TestServers; + +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; + +import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpServerCodec; + +/** + * {@link TestServer} subtype that performs WebWhois Services Expected + * + * It will either redirect the client to the correct location if given the + * requisite redirect input, give the client a successful response if they give + * the expected final destination, or give the client an error message if given + * an unexpected host location + */ +public class WebWhoisServer extends TestServer { + + public WebWhoisServer(LocalAddress localAddress, ImmutableList handlers) { + super(localAddress, handlers); + } + + public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + super(eventLoopGroup, localAddress, handlers); + } + + /** Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the HttpRequestMessage object through pipeline */ + public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + return new WebWhoisServer( + eventLoopGroup, + localAddress, + ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) + ); + } + /** Creates server that sends exactly what we expect a remote server to send as a response, by sending the {@link ByteBuf} of the response through pipeline */ + public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + return new WebWhoisServer( + eventLoopGroup, + localAddress, + ImmutableList.of( + new HttpServerCodec(), + new HttpObjectAggregator(1048576), + new RedirectHandler(redirectInput, destinationInput)) + ); + } + + /** + * Handler that will wither redirect client, give successful response, or give error messge + */ + @Sharable + static class RedirectHandler extends ChannelDuplexHandler { + private String redirectInput; + private String destinationInput; + + /** + * + * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + */ + public RedirectHandler(String redirectInput, String destinationInput) { + this.redirectInput = redirectInput; + this.destinationInput = destinationInput; + } + + /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + HttpRequest request = (HttpRequest) msg; + HttpResponse response; + if (request.headers().get("host").equals(redirectInput)) { + response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + } else if (request.headers().get("host").equals(destinationInput)) { + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + } else { + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + } + ctx.channel().writeAndFlush(response); + + } + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index c0c5831a68c..8d1722c9625 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,26 +14,47 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.joda.time.Duration; -/** - * Utility class for various helper methods used in testing. - */ +/** Utility class for various helper methods used in testing. */ public class TestUtils { + static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -54,33 +75,110 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { return response; } - /** - * Creates HttpResponse given status, redirection location, and other necessary inputs - */ + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain"); + response.headers().set("content-type", "text/plain").set("content-length", "0"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } return response; } - /** - * Basic outline for {@link Token} instances to be used in tests - */ - abstract static class TestToken extends Token { + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); + return response; + } + + /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ + public static class TestProvider implements Provider { + + private E obj; + + public TestProvider(E obj) { + this.obj = obj; + } + + @Override + public E get() { + return obj; + } + } + + /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ + public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { + + String message; + + public DuplexMessageTest() { + message = ""; + } + + public DuplexMessageTest(String msg) { + message = msg; + } + + @Override + public String toString() { + return message; + } + } + + /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ + public static class TestStep extends ProbingStep { - protected String host; + public TestStep(Protocol protocol, String testMessage, LocalAddress address) { + super(protocol, new DuplexMessageTest(testMessage)); + this.address = address; + this.duration = Duration.ZERO; + } + } + + /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ + public static class DummyStep extends ProbingStep { + private DefaultPromise future; + + public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { + super(protocol, new DuplexMessageTest()); + future = new DefaultPromise(eventLoopGroup.next()) {}; + duration = Duration.ZERO; + } + + @Override + public void accept(Token token) { + future.setSuccess(token); + } + public DefaultPromise getFuture() { + return future; + } + } + + /** Basic outline for {@link Token} instances to be used in tests */ + private static abstract class TestToken extends Token { + private String host; protected TestToken(String host) { this.host = host; } - @Override public Token next() { return this; @@ -92,35 +190,63 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String host() { + public String getHost() { return host; } } - /** - * {@link TestToken} instance that creates new channel - */ + /** {@link TestToken} instance that creates new channel */ public static class NewChannelToken extends TestToken { - public NewChannelToken(String host) { super(host); } - @Override public Channel channel() { return null; } } - /** - * {@link TestToken} instance that passes in existing channel - */ + /** {@link TestToken} instance that passes in existing channel */ public static class ExistingChannelToken extends TestToken { + private Channel channel; + public ExistingChannelToken(Channel channel, String host) { super(host); this.channel = channel; } + @Override + public Channel channel() { + return channel; + } + } + + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index 295bb809a13..ef5cba5b60d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,11 +16,12 @@ import static com.google.common.truth.Truth.assertThat; -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,21 +34,21 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); + private static String TEST_DOMAIN = "test"; - public Token webToken = new WebWhoisToken(TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAIN); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 987abbfd7dc..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,38 +17,31 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link - * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to + * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** - * Handles inbound conversion - */ + /** Handles inbound conversion */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } - /** - * Handles outbound conversion - */ + /** Handles outbound conversion */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index f51f8c8fd61..b6b5e8fbe0c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -25,11 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingActionTest; -import google.registry.monitoring.blackbox.ProbingStepTest; -import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.testservers.WebWhoisServer; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -41,6 +41,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -51,25 +52,24 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest} - *

+ *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

*/ public final class NettyRule extends ExternalResource { + // All I/O operations are done inside the single thread within this event loop group, which is // different from the main test thread. Therefore synchronizations are required to make sure that // certain I/O activities are finished when assertions are performed. public NettyRule() { eventLoopGroup = new NioEventLoopGroup(1); } - public NettyRule(EventLoopGroup e) { eventLoopGroup = e; } - private final EventLoopGroup eventLoopGroup; + private WebWhoisServer webWhoisServer; // Handler attached to server's channel to record the request received. private EchoHandler echoHandler; @@ -79,24 +79,17 @@ public NettyRule(EventLoopGroup e) { private Channel channel; - /** - * Sets up a server channel bound to the given local address. - */ - public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { + /** Sets up a server channel bound to the given local address. */ + public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - - new WebWhoisServer(eventLoopGroup, localAddress, - ImmutableList.builder().add(handlers).add(echoHandler).build()); + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); } - /** - * Sets up a client channel connecting to the give local address. - */ + /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - Protocol protocol, - String host, + ProbingAction probingAction, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -116,9 +109,7 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol) - .attr(REMOTE_ADDRESS_KEY, host); - + .attr(PROBING_ACTION_KEY, probingAction); channel = b.connect(localAddress).syncUninterruptibly().channel(); } @@ -126,10 +117,8 @@ private void checkReady() { checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); } - /** - * Test that custom setup to send message to current server sends right message - */ - public void assertReceivedMessage(String message) throws Exception { + /** Test that custom setup to send message to current server sends right message */ + public void assertThatCustomWorks(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -137,9 +126,9 @@ public void assertReceivedMessage(String message) throws Exception { /** * Test that a message can go through, both inbound and outbound. * - *

The client writes the message to the server, which echos it back and saves the string in - * its promise. The client receives the echo and saves it in its promise. All these activities - * happens in the I/O thread, and this call itself returns immediately. + *

The client writes the message to the server, which echos it back and saves the string in its + * promise. The client receives the echo and saves it in its promise. All these activities happens + * in the I/O thread, and this call itself returns immediately. */ void assertThatMessagesWork() throws Exception { checkReady(); @@ -170,42 +159,8 @@ ThrowableSubject assertThatClientRootCause() { } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** - * Saves any inbound error as the cause of the promise failure. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } - - /** - * A handler that dumps its inbound message to a promise that can be inspected later. - */ + /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture responseFuture = new CompletableFuture<>(); @@ -226,9 +181,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception responseFuture.complete(response); } - /** - * Saves any inbound error into the failure cause of the promise. - */ + /** Saves any inbound error into the failure cause of the promise. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 25e5608a100..469c62a8f75 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,14 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.ExistingChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; @@ -41,6 +45,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; +import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -62,14 +67,12 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - /** - * Fake host to test if the SSL engine gets the correct peer host. - */ + private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); + + /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; - /** - * Fake port to test if the SSL engine gets the correct peer port. - */ + /** Fake port to test if the SSL engine gets the correct peer port. */ private static final int SSL_PORT = 12345; @Rule @@ -82,24 +85,23 @@ public class SslClientInitializerTest { @Parameters(name = "{0}") public static SslProvider[] data() { return OpenSsl.isAvailable() - ? new SslProvider[]{SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[]{SslProvider.JDK}; + ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[] {SslProvider.JDK}; } - /** - * Saves the SNI hostname received by the server, if sent by the client. - */ + /** Saves the SNI hostname received by the server, if sent by the client. */ private String sniHostReceived; - /** - * Fake protocol saved in channel attribute. - */ - private static final Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + /** Fake protocol saved in channel attribute. */ + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .persistentConnection(false) + .build(); + + private ProbingAction probingAction; private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -111,13 +113,23 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } + private void setupProbingAction(Channel channel) { + probingAction = ExistingChannelAction.builder() + .delay(Duration.ZERO) + .host(SSL_HOST) + .channel(channel) + .outboundMessage(DEFAULT_MESSAGE) + .protocol(PROTOCOL) + .build(); + } + @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - channel.attr(PROTOCOL_KEY).set(PROTOCOL); - channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); + setupProbingAction(channel); + channel.attr(PROBING_ACTION_KEY).set(probingAction); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -148,7 +160,8 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -174,9 +187,10 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -203,9 +217,10 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index be42536823f..518bb9ba686 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,22 +14,20 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; /** - * Concrete implementation of {@link ActionHandler} that does nothing different from parent class - * other than store and return the {@code inboundMessage} + * Concrete implementation of {@link ActionHandler} that does nothing different from + * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 63bb2cf5b53..d8a672758da 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,32 +15,44 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; +import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ +/** + * Unit tests for {@link WebWhoisActionHandler}. + * + *

Attempts to test how well {@link WebWhoisActionHandler} works + * when responding to all possible types of responses

+ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; @@ -50,89 +62,96 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; + private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); + private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - + private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; + private ProbingAction probingAction; + private Provider actionHandlerProvider; + private void generateLocalAddress() { + address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + } /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { + private Protocol createProtocol(String name, int port) { return Protocol.builder() .name(name) .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); + .handlerProviders(ImmutableList.of(actionHandlerProvider)) + .persistentConnection(false) + .build(); } /** Initializes new WebWhoisActionHandler */ private void setupActionHandler() { actionHandler = new WebWhoisActionHandler(); + actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); + private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + setupProbingActionBasic( + protocol, + outboundMessage, + makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); + channel.attr(PROBING_ACTION_KEY).set(probingAction); } + private Bootstrap makeBootstrap(EventLoopGroup group) { + return new Bootstrap() + .group(group) + .channel(LocalChannel.class); + } /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() + private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + probingAction = NewChannelAction.builder() .protocol(protocol) .outboundMessage(outboundMessage) .delay(DEFAULT_DURATION) .bootstrap(bootstrap) + .host(TARGET_HOST) + .address(DEFAULT_ADDRESS) .build(); } - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); + private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(host) + .address(address) + .build(); } - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; + private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testSuccess_responseOk() { + public void testBasic_responseOk() throws Exception { //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -140,25 +159,30 @@ public void testSuccess_responseOk() { channel.writeInbound(response); - //assesses that we successfully receivved good response and protocol is unchanged + //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testSuccess_responseBad() { + public void testBasic_responseFailure() { //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseBad", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + FullHttpResponse response = HttpResponseMessage + .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -167,24 +191,63 @@ public void testSuccess_responseBad() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + } + @Test + public void testBasic_responseError() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseError", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + + //stores future + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, and event is success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testSuccess_redirectCloseChannel() { + public void testBasic_redirectCloseChannel() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); + HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", 0); + generateLocalAddress(); + setupChannel(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(outboundMessage); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + //checks that future has not been set to successful or a failure + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); @@ -195,27 +258,69 @@ public void testSuccess_redirectCloseChannel() { } @Test - public void testSuccess_redirectHost() { + public void testBasic_redirectHost() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); channel.writeInbound(originalResponse); + ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); + Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); + assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); + } + + @Test + public void testAdvanced_responseOk() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", TARGET_HOST, group); + //stores future + ChannelFuture future = probingAction.call(); + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + } + + @Test + public void testAdvanced_responseFailure() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", TARGET_HOST, group); + + //stores future + ChannelFuture future = probingAction.call(); + + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } } + From 5551bcbdd989dde37d48ea76a242fd3b71a802b3 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 243/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 48 --- .../monitoring/blackbox/NewChannelAction.java | 135 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProberModule.java | 80 ++--- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingSequence.java | 129 ++++---- .../monitoring/blackbox/ProbingStep.java | 146 +++++----- .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/Protocol.java | 78 +---- .../monitoring/blackbox/TokenModule.java | 37 --- .../monitoring/blackbox/Tokens/Token.java | 45 --- .../blackbox/Tokens/WebWhoisToken.java | 57 ---- .../monitoring/blackbox/WebWhoisModule.java | 169 ++++++----- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/ActionHandler.java | 102 +++++-- .../blackbox/handlers/MessageHandler.java | 6 - .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../handlers/WebWhoisMessageHandler.java | 31 +- .../blackbox/messages/HttpRequestMessage.java | 65 ++++- .../messages/HttpResponseMessage.java | 38 +-- .../messages/OutboundMessageType.java | 10 +- .../monitoring/blackbox/tokens/Token.java | 43 +-- .../blackbox/tokens/WebWhoisToken.java | 62 ++-- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 32 files changed, 766 insertions(+), 1009 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index a9c93804da6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 56939e525e1..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ - public abstract LocalAddress address(); - - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ - private Channel channel; - - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ - abstract Bootstrap bootstrap(); - - /** {@link Channel} object instantiated in {@code call()} */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } - -} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..63a43ad4537 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,32 +14,24 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 73bd9127852..0daaf16ded4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,99 +14,59 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; import javax.inject.Singleton; +import org.joda.time.Duration; /** - * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} - * - *

Provides

+ * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores + * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. */ @Module public class ProberModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; + /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + private static final Duration DEFAULT_DURATION = new Duration(4000L); + + /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides - @HttpWhoisProtocol - ProbingSequence provideHttpWhoisSequence( - @HttpWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpsWhoisProtocol - ProbingSequence provideHttpsWhoisSequence( - @HttpsWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return httpWhoIsPort; - } - - @Provides - @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return httpsWhoIsPort; + @Singleton + Duration provideDuration() { + return DEFAULT_DURATION; } + /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - ImmutableMap providePortToProtocolMap( - Set protocolSet) { - return Maps.uniqueIndex(protocolSet, Protocol::port); + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - - + /** Root level {@link Component} that provides each {@link ProbingSequence}. */ @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, - TokenModule.class }) public interface ProberComponent { - @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); - - @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); - - ImmutableMap providePortToProtocolMap(); - - @WebWhoisProtocol Token provideWebWhoisToken(); + //Standard WebWhois sequence + @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6387207fea4..2dbf48256f9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,109 +14,100 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} - * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ - private EventLoopGroup eventGroup; + /**Each {@link ProbingSequence} requires a start token to begin running. */ + private Token startToken; - /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ - private Bootstrap bootstrap; - - public Bootstrap getBootstrap() { - return bootstrap; - } - - public void start(Token token) { - // calls the first step with input token; - firstStep.accept(token); + public void start() { + // calls the first step with startToken; + firstStep.accept(startToken); } /** - * {@link Builder} which takes in {@link ProbingStep}s - * - * @param Same specified {@code C} for overall {@link ProbingSequence} + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. */ - public static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstSequenceStep; - private EventLoopGroup eventLoopGroup; - private Class classType; - - Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public static class Builder { + + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstRepeatedStep; + private Bootstrap bootstrap; + private Token startToken; + + /** + * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. + * + *

Must be called before adding {@link ProbingStep.Builder}s.

+ */ + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; return this; } - Builder addStep(ProbingStep step) { - if (currentStep == null) { + /** Adds start token that activate {@link ProbingSequence}. */ + public Builder addToken(Token token) { + startToken = token; + return this; + } + + /** + * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * built, and pointed to by the previous {@link ProbingStep} added. + */ + public Builder addStep(ProbingStep.Builder stepBuilder) { + assert (bootstrap != null); + ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + + if (currentStep == null) firstStep = step; - } else { + else currentStep.nextStep(step); - } + currentStep = step; return this; } - /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ - Builder makeFirstRepeated() { - firstSequenceStep = currentStep; - return this; - } - /** Set the class to be the same as {@code C} */ - public Builder setClass(Class classType) { - this.classType = classType; + /** We take special note of the first repeated step. */ + public Builder markFirstRepeated() { + firstRepeatedStep = currentStep; return this; } - public ProbingSequence build() { - currentStep.nextStep(firstSequenceStep); + /** + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and + * calls private constructor to create {@link ProbingSequence}. + */ + public ProbingSequence build() { + if (firstRepeatedStep == null) + firstRepeatedStep = firstStep; + + currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); - return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + return new ProbingSequence(this.firstStep, this.startToken); } - } - /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ - private void setParents() { - ProbingStep currentStep = firstStep.parent(this).nextStep(); - - while (currentStep != firstStep) { - currentStep = currentStep.parent(this).nextStep(); - } - } - private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, - Class classType) { + private ProbingSequence(ProbingStep firstStep, Token startToken) { this.firstStep = firstStep; - this.eventGroup = eventLoopGroup; - this.bootstrap = new Bootstrap() - .group(eventGroup) - .channel(classType); - setParents(); - } - - @Override - public String toString() { - return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); - + this.startToken = startToken; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 5bad5abf6bf..d54acef325a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,155 +14,143 @@ package google.registry.monitoring.blackbox; +import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.local.LocalAddress; -import java.io.IOException; import java.util.function.Consumer; import org.joda.time.Duration; /** - * Represents generator of actions performed at each step in {@link ProbingSequence} - * - * @param See {@code C} in {@link ProbingSequence} + * {@link AutoValue} class that represents generator of actions performed at each step + * in {@link ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies - * these components on each loop iteration with the consumed {@link Token} and from that, - * generates new {@link ProbingAction} to perform<./p> + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. + * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, + * generates a new {@link ProbingAction} to call.

* - *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -public abstract class ProbingStep implements Consumer { +@AutoValue +public abstract class ProbingStep implements Consumer { - public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); - protected static final Duration DEFAULT_DURATION = new Duration(2000L); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - protected LocalAddress address = DEFAULT_ADDRESS; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ private boolean isLastStep = false; - private ProbingStep nextStep; - private ProbingSequence parent; + private ProbingStep nextStep; - protected Duration duration; + abstract Duration duration(); + abstract Protocol protocol(); + abstract OutboundMessageType messageTemplate(); + abstract Bootstrap bootstrap(); - protected final Protocol protocol; - protected final OutboundMessageType message; - protected ProbingStep(Protocol protocol, OutboundMessageType message) { - this.protocol = protocol; - this.message = message; - } + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder setDuration(Duration value); - private OutboundMessageType message() { - return message; - } + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); - Protocol protocol() { - return protocol; + public abstract ProbingStep build(); } + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - ProbingStep parent(ProbingSequence parent) { - this.parent = parent; - return this; - } - - /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ private ProbingAction generateAction(Token token) throws InternalException { - ProbingAction generatedAction; - - OutboundMessageType message = token.modifyMessage(message()); - - //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction - if (protocol().persistentConnection() && token.channel() != null) { - generatedAction = ExistingChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .channel(token.channel()) - .build(); - } else { - generatedAction = NewChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .bootstrap(parent.getBootstrap()) - .address(address) - .build(); - - } - return generatedAction; + OutboundMessageType message = token.modifyMessage(messageTemplate()); + ProbingAction.Builder probingActionBuilder = ProbingAction.builder() + .setDelay(duration()) + .setProtocol(protocol()) + .setOutboundMessage(message) + .setHost(token.getHost()) + .setBootstrap(bootstrap()); + + if (token.channel() != null) + probingActionBuilder.setChannel(token.channel()); + + return probingActionBuilder.build(); } - /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } @Override public void accept(Token token) { - ProbingAction nextAction; + ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - nextAction = generateAction(token); + currentAction = generateAction(token); } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - //If the next step maintains the connection, pass on the channel from this - if (protocol().persistentConnection()) { - token.channel(nextAction.channel()); - } + //call the created action - ChannelFuture future = nextAction.call(); + ChannelFuture future; + + try { + future = currentAction.call(); + + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Performed"); + nextStep.accept(generateNextToken(token)); + return; + } + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - nextStep.accept(generateNextToken(token)); + //If the next step maintains the connection, pass on the channel from this } else { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + token.setChannel(currentAction.channel()); + + nextStep.accept(generateNextToken(token)); + + }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n" + - "and parent sequence: %s", + "OutboundMessage: %s\n", protocol(), - message(), - parent); + messageTemplate().getClass().getName()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 06ce0532da0..2f4a9342337 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,95 +16,43 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; +import io.netty.util.AttributeKey; import javax.inject.Provider; /** - * Protocol Class packages all static variables necessary for a certain type of connection - * Both the host and the path can be changed for the same protocol - * Mainly packages the handlers necessary for the requisite channel pipeline + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. */ @AutoValue public abstract class Protocol { - public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - - /** - * Default names associated with each protocol - */ - final static String EPP_PROTOCOL_NAME = "EPP"; - final static String DNS_PROTOCOL_NAME = "DNS"; - final static String WHOIS_PROTOCOL_NAME = "WHOIS"; - final static String RDAP_PROTOCOL_NAME = "RDAP"; - - private String host; - private String path = ""; - private ProbingAction probingAction; - - /** Setter method for Protocol's host*/ - public Protocol host(String host) { - this.host = host; - return this; - } + /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - /** Getter method for Protocol's host*/ - public String host() { - return host; - } - - /** Setter method for Protocol's path*/ - public Protocol path(String path) { - this.path = path; - return this; - } - - /** Getter method for Protocol's path*/ - public String path() { - return path; - } + abstract String name(); - /** Setter method for Protocol's ProbingAction parent*/ - public Protocol probingAction(ProbingAction probingAction) { - this.probingAction = probingAction; - return this; - } - - /** Getter method for Protocol's path*/ - public ProbingAction probingAction() { - return probingAction; - } - - /** If connection associated with Protocol is persistent, which is only EPP */ - public boolean persistentConnection() { - return name() == EPP_PROTOCOL_NAME; - } - - /** Protocol Name */ - public abstract String name(); - - /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - public abstract ImmutableList> handlerProviders(); - + abstract ImmutableList> handlerProviders(); - public abstract Builder toBuilder(); + /** Boolean that notes if connection associated with Protocol is persistent.*/ + abstract boolean persistentConnection(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } - @AutoValue.Builder public static abstract class Builder { - public abstract Builder name(String value); + public abstract Builder setName(String value); + + public abstract Builder setPort(int num); - public abstract Builder port(int num); + public abstract Builder setHandlerProviders(ImmutableList> providers); - public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder setPersistentConnection(boolean value); public abstract Protocol build(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index ba656a38b87..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } - - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index aa3a6c58959..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - public Channel channel() { - return this.channel; - } - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 03e12666313..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } - - -} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dba905c0e49..f9e9edfc6ad 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,62 +17,86 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; -import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandler; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - final static String DOMAIN_SUFFIX = "whois.nic."; + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + private static final String DOMAIN_PREFIX = "whois.nic."; + + /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + private static final int maximumMessageLengthBytes = 512 * 1024; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - - - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - - + /** {@link Provides} standard WebWhois sequence. */ @Provides - @HttpWhoisProtocol - static ProbingStep provideHttpWhoisProbingSequence( - @HttpWhoisProtocol Protocol httpWhoisProtocol) { - return new ProbingStepWeb<>(httpWhoisProtocol); + @WebWhoisProtocol + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, + WebWhoisToken webWhoisToken, + @WebWhoisProtocol Bootstrap bootstrap) { + + return new ProbingSequence.Builder() + .addToken(webWhoisToken) + .setBootstrap(bootstrap) + .addStep(probingStepBuilder) + .build(); } + + /** {@link Provides} only step used in WebWhois sequence. */ @Provides - @HttpsWhoisProtocol - static ProbingStep provideHttpsWhoisProbingStep( - @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { - return new ProbingStepWeb<>(httpsWhoisProtocol); + @WebWhoisProtocol + static ProbingStep.Builder provideWebWhoisStepBuilder( + @HttpWhoisProtocol Protocol httpWhoisProtocol, + HttpRequestMessage messageTemplate, + Duration duration) { + + return ProbingStep.builder() + .setProtocol(httpWhoisProtocol) + .setMessageTemplate(messageTemplate) + .setDuration(duration); } - + /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides @HttpWhoisProtocol @@ -80,28 +104,14 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpProtocolForSet( - @HttpWhoisProtocol int httpWhoisPort, - @HttpWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTP_PROTOCOL_NAME) + .setPort(httpWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } - + /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ @Singleton @Provides @HttpsWhoisProtocol @@ -109,40 +119,28 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpsProtocolForSet( - @HttpsWhoisProtocol int httpsWhoisPort, - @HttpsWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTPS_PROTOCOL_NAME) + .setPort(httpsWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } + /** {@link Provides} the prefix where we probe: "prefix.tld". */ @Provides - @WebWhoisProtocol - String provideHttpWhoisHost() { - return "app"; + @Named("Web-WHOIS-Prefix") + String provideWhoisPrefix() { + return DOMAIN_PREFIX; } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -151,13 +149,14 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -167,33 +166,57 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } + @Provides + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); + } + + @Provides + static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { + return new HttpObjectAggregator(maxContentLength); + } + + /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + @Provides + @HttpsWhoisProtocol + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); + } + /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + @Singleton @Provides @WebWhoisProtocol - static MessageHandler provideMessageHandler() { - return new WebWhoisMessageHandler(); + static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + return new Bootstrap() + .group(eventLoopGroup) + .channel(NioSocketChannel.class); } @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); + @WebWhoisProtocol + int provideMaximumMessageLengthBytes() { + return maximumMessageLengthBytes; } + /** {@link Provides} the list of top level domains to be probed */ + @Singleton @Provides - static HttpObjectAggregator provideHttpObjectAggregator() { - return new HttpObjectAggregator(1048576); + @WebWhoisProtocol + ImmutableList provideTopLevelDomains() { + return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); } @Provides - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index 776a231d6dd..be3d725c833 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,10 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when the action - * performed failed due to an issue in the connection with the server. + * Base exception class for all instances when the status of the action performed is ERROR. */ -public class ConnectionException extends UndeterminedStateException { +public class ConnectionException extends Exception { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index 31196d776f4..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 7898203e92d..e397393b4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,10 +14,11 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; @@ -26,16 +27,18 @@ import io.netty.channel.ChannelPromise; /** - *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} - * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception - * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses - * specify further work to be done for specific kinds of channel pipelines.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed + * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} + * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * + *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -47,28 +50,42 @@ public enum ResponseType {SUCCESS, FAILURE, ERROR} /** Status of response for current {@link ActionHandler} instance */ private static ResponseType status; + /** {@link ChannelPromise} that informs {@link google.registry.monitoring.blackbox.ProbingAction} if response has been received. */ protected ChannelPromise finished; - /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** Returns initialized {@link ChannelPromise} to {@link google.registry.monitoring.blackbox.ProbingAction}.*/ public ChannelFuture getFuture() { return finished; } - /** Initializes new {@link ChannelPromise} */ + /** Initializes the same {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } + /** Initializes the same {@link ChannelPromise} in case current channel is reused (usually for EPP).*/ + public void resetFuture() { + finished = finished.channel().newPromise(); + } + + /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { - //simply marks finished as success + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { + status = ResponseType.SUCCESS; - finished.setSuccess(); + + if (!finished.isSuccess()) { + finished.setSuccess(); + } } - /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ + /** + * Logs the channel and pipeline that caused error, closes channel, then informs + * {@link google.registry.monitoring.blackbox.ProbingAction} listeners of error. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).log(String.format( @@ -76,27 +93,62 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.channel().toString(), ctx.channel().pipeline().toString())); - - if (ResponseException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + if (cause instanceof ResponseException) { + //On ResponseException, we know the response is a failure. As a result, + //we set the status to FAILURE, then inform the MetricsHandler of this status = ResponseType.FAILURE; + + //Since it wasn't a success, we still want to log to see what caused the FAILURE logger.atInfo().log(cause.getMessage()); + + //As always, inform the ProbingStep that we successfully completed this action finished.setSuccess(); - } else if (ServerSideException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + + } else if (cause instanceof ConnectionException) { + //On ConnectionException, we know the response type is an error. As a result, + //we set the status to ERROR, then inform the MetricsHandler of this status = ResponseType.ERROR; + + //Since it wasn't a success, we still log what caused the ERROR logger.atInfo().log(cause.getMessage()); finished.setSuccess(); - } else if (InternalException.class.isInstance(cause)){ + + //As this was an ERROR in the connection, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + } else if (cause instanceof InternalException){ + //For an internal error, metrics should not be collected, so we log what caused this, and + //inform the ProbingStep the Prober had an internal error on this action logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); + + + //As this was an internal error, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } else { - finished.setFailure(cause); + //In the case of any other kind of error, we assume it is some type of connection ERROR, + //so we treat it as such: + + status = ResponseType.ERROR; + + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - //due to failure, close channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + + } + + /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ + @VisibleForTesting + ResponseType getStatus() { + return status; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index ac18e5db0b1..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,6 +0,0 @@ -package google.registry.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -public abstract class MessageHandler extends ChannelDuplexHandler { -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index ac844ac99df..919006592ea 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -89,8 +90,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); - Protocol protocol = action.protocol(); + Protocol protocol = channel.attr(PROTOCOL_KEY).get(); + String host = channel.attr(REMOTE_ADDRESS_KEY).get(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -103,7 +104,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), action.host(), protocol.port()); + .newHandler(channel.alloc(), host, protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 4afc5d95ba7..58c395ad86e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,33 +1,52 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -public class WebWhoisMessageHandler extends MessageHandler { - - private HttpRequestMessage request; +/** + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} + * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} + * in case of reuse for redirection. + */ +public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject public WebWhoisMessageHandler() {} + /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - request = (HttpRequestMessage) msg; + HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - FullHttpResponse originalResponse = (FullHttpResponse) msg; - InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); + HttpResponseMessage response = new HttpResponseMessage(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -5,19 +19,28 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

+ */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - @Override @@ -26,16 +49,30 @@ public HttpRequestMessage setUri(String path) { return this; } - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } + + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; + } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + throw new IllegalArgumentException(); } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + } + + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,23 +33,10 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); - - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } - - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 0dd17e9d4a9..be6c872cc3e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,8 +14,16 @@ package google.registry.monitoring.blackbox.messages; +import google.registry.monitoring.blackbox.exceptions.InternalException; + /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType {} +public interface OutboundMessageType { + + /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + public OutboundMessageType modifyMessage(String... args) throws InternalException; + /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + public String name(); +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index b10c45dae8a..dd1882b5686 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,58 +14,41 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.ProbingSequence; -import google.registry.monitoring.blackbox.ProbingStep; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} in a single loop of a - * {@link ProbingSequence}. + * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} + * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes on channel that remains unchanged within a - * loop of the sequence.

+ * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop * in the sequence.

*/ public abstract class Token { - /** - * {@link Channel} that always starts out as null. Once a persistent connection is made (such as - * EPP), that channel is stored in the token and passed on to later steps in the sequence until a - * new loop begins. - */ + /** {@link Channel} that always starts out as null. */ protected Channel channel; - /** - * Obtains next {@link Token} for next loop in sequence. - */ + /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); - /** - * String corresponding to host that is relevant for loop in sequence. - */ - public abstract String host(); + /** String corresponding to host that is relevant for loop in sequence. */ + public abstract String getHost(); - /** - * Modifies the {@link OutboundMessageType} in the manner necessary for each loop - */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) - throws UndeterminedStateException; + /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; - /** - * Set method for {@code channel} - */ + /** Set method for {@code channel} */ public void setChannel(Channel channel) { this.channel = channel; } - /** - * Get method for {@code channel}. - */ + /** Get method for {@code channel}. */ public Channel channel() { return this.channel; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 3ff852f3556..2847e5ce0eb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,67 +16,59 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; +import java.util.List; import javax.inject.Inject; +import javax.inject.Named; /** * {@link Token} subtype designed for WebWhois sequence. * *

Between loops of a WebWhois sequence the only thing changing is the tld we - * are probing. As a result, we maintain the list of {@code topLevelDomains} and on each call to - * next, have our index looking at the next {@code topLevelDomain}.

+ * are probing. As a result, we maintain the list of {@code topLevelDomains} and + * on each call to next, have our index looking at the next {@code topLevelDomain}.

*/ public class WebWhoisToken extends Token { - /** - * For each top level domain (tld), we probe "prefix.tld". - */ - private static final String PREFIX = "whois.nic."; + /** For each top level domain (tld), we probe "prefix.tld". */ + private final String prefix; - /** - * {@link ImmutableList} of all top level domains to be probed. - */ - private final Iterator topLevelDomainsIterator; + /** {@link ImmutableList} of all top level domains to be probed. */ + private final ImmutableList topLevelDomains; - /** - * Current index of {@code topLevelDomains} that represents tld we are probing. - */ - private String currentDomain; + /** Current index of {@code topLevelDomains} that represents tld we are probing. */ + private int domainsIndex; @Inject - public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken( + @Named("Web-WHOIS-Prefix") String prefix, + @WebWhoisProtocol ImmutableList topLevelDomains) { - topLevelDomainsIterator = topLevelDomains.iterator(); - currentDomain = topLevelDomainsIterator.next(); + domainsIndex = 0; + this.prefix = prefix; + this.topLevelDomains = topLevelDomains; } - /** - * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. - */ + /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + domainsIndex += 1; + domainsIndex %= topLevelDomains.size(); return this; } - /** - * Modifies message to reflect the new host coming from the new top level domain. - */ + /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) - throws UndeterminedStateException { - return original.modifyMessage(host()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { + return original.modifyMessage(getHost()); } - /** - * Returns host as the concatenation of fixed {@code prefix} and current value of {@code - * topLevelDomains}. - */ + /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String host() { - return PREFIX + currentDomain; + public String getHost() { + return prefix + topLevelDomains.get(domainsIndex); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Mon, 29 Jul 2019 12:04:58 -0400 Subject: [PATCH 244/337] Minor Style Fixes --- .../monitoring/blackbox/ProbingAction.java | 85 ++++++++++--------- .../monitoring/blackbox/ProbingStep.java | 8 +- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..3f6a962b12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -89,11 +90,47 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** The {@link SocketAddress} instance that specifies remote address of connection */ + @Nullable public abstract SocketAddress address(); /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ public abstract Optional bootstrap(); + + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> actionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** * The method that performs the work of the actual action. * @@ -130,41 +167,13 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } @@ -224,7 +233,7 @@ public abstract static class Builder { abstract Channel channel(); - abstract Optional address(); + abstract SocketAddress address(); abstract Optional bootstrap(); @@ -233,7 +242,7 @@ public abstract static class Builder { abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) + if (address() == null) //If no address has been supplied, we set it based on the host and port setAddress(new InetSocketAddress(host(), protocol().port())); @@ -259,7 +268,7 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap().get().connect(address()); setChannel(connectionFuture.channel()); setConnectionFuture(connectionFuture); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index d54acef325a..47c89c72c11 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -21,7 +21,9 @@ import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import java.net.SocketAddress; import java.util.function.Consumer; +import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -48,6 +50,7 @@ public abstract class ProbingStep implements Consumer { abstract Protocol protocol(); abstract OutboundMessageType messageTemplate(); abstract Bootstrap bootstrap(); + @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -60,6 +63,8 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); + public abstract Builder setAddress(SocketAddress address); + public abstract ProbingStep build(); } @@ -87,7 +92,8 @@ private ProbingAction generateAction(Token token) throws InternalException { .setProtocol(protocol()) .setOutboundMessage(message) .setHost(token.getHost()) - .setBootstrap(bootstrap()); + .setBootstrap(bootstrap()) + .setAddress(address()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); From 8dc86a16885e12be1272f36fe132935f21f8933a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:05:59 -0400 Subject: [PATCH 245/337] Updated build.gradle file --- prober/build.gradle | 8 - .../blackbox/ProbingSequenceStepTest.java | 219 ----------------- .../blackbox/ProbingSequenceTest.java | 123 ---------- .../monitoring/blackbox/ProbingStepTest.java | 223 +++++++++--------- 4 files changed, 110 insertions(+), 463 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java diff --git a/prober/build.gradle b/prober/build.gradle index b23314728e1..bb3b59ce8d7 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,8 +16,6 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - - dependencies { def deps = rootProject.dependencyMap @@ -46,7 +44,6 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -55,8 +52,3 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } - -task(runMain, dependsOn: 'classes', type: JavaExec) { - main = 'google.registry.monitoring.blackbox.Prober' - classpath = sourceSets.main.runtimeClasspath -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java deleted file mode 100644 index 7a713017072..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.TestUtils.TestStep; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.handlers.ConversionHandler; -import google.registry.monitoring.blackbox.handlers.NettyRule; -import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; -import org.junit.Rule; -import org.junit.Test; - -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { - - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ - private ProbingSequence testSequence; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); - dummyStep = new DummyStep(testProtocol, eventLoopGroup); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(false) - .build(); - } - - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(true) - .build(); - } - - /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ - private void setupSequence() { - testSequence = new ProbingSequence.Builder() - .eventLoopGroup(eventLoopGroup) - .setClass(LocalChannel.class) - .addStep(firstStep) - .makeFirstRepeated() - .addStep(dummyStep) - .build(); - } - - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.nextStep()).isNull(); - - //we expect that this exception be thrown - assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); - - } - - @Test - public void testWithSequence_NewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupSequence(); - setupNewChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupSequence(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 8d9e45c6a66..2b0559514a2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,128 +1,5 @@ -// Copyright 2019 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.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; - -import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import java.net.SocketAddress; -import org.joda.time.Duration; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) public class ProbingSequenceTest { - private final static String TEST_HOST = "TEST_HOST"; - - - private Token testToken = new ProbingSequenceTestToken(); - - /** - * Custom {@link ProbingStep} subclass that acts as a mock - * step, so we can test how well {@link ProbingSequence} builds - * a linked list of {@link ProbingStep}s from their {@link Builder}s. - */ - private static class TestStep extends ProbingStep { - private String marker; - - /** We implement all abstract methods to simply return null, as we have no use for them here. */ - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ - @Override - Bootstrap bootstrap() { - return null; - } - - public TestStep(String marker) { - this.marker = marker; - } - - /** - * On a call to accept, we modify the token to reflect what the current step is, so we can get - * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated - * in order. - */ - @Override - public void accept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - if (!isLastStep) { - nextStep().accept(token); - } else { - ((TestStep)nextStep()).specialAccept(token); - } - } - - /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ - public void specialAccept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - return; - } - } - - @Test - public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(firstStep) - .addStep(secondStep) - .addStep(thirdStep) - .build(); - - sequence.start(); - - assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); - } - - @Test - public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(thirdStep) - .addStep(secondStep) - .markFirstRepeated() - .addStep(firstStep) - .build(); - - sequence.start(); - - assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 307d19221dd..090753014e4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,203 +11,200 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.TestUtils.dummyStep; +import static google.registry.monitoring.blackbox.TestUtils.testStep; +import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; -import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; -import org.mockito.Mockito; - -/** - * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific - * implementations - */ -public class ProbingStepTest { - - /** - * Basic Constants necessary for tests - */ - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final int PROTOCOL_PORT = 0; - private static final String TEST_MESSAGE = "TEST_MESSAGE"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - private static final LocalAddress ADDRESS = new LocalAddress(ADDRESS_NAME); + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - /** - * Used for testing how well probing step can create connection to blackbox server - */ + /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** - * The two main handlers we need in any test pipeline used that connects to {@link NettyRule's - * server} - **/ + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** - * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} - * is called, it just marks the supplied future as succeeded, returning the requisite token. - */ - private ProbingStep dummyStep() { - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(dummyStep).nextStep(); - return dummyStep; + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); } + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } - @Test - public void testNewChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } - // Sets up Protocol for when we create a new channel. - Protocol testProtocol = Protocol.builder() + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); + dummyStep = dummyStep(eventLoopGroup); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); + } - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) .build(); + } - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); + //there should be no next step + assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); - //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(ADDRESS); + } + + @Test + public void testNewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //checks that we have appropriately sent the write message to server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - verify(dummyStep, times(1)).accept(any(Token.class)); + assertThat(future.get()).isEqualTo(testToken); + } - @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - - // Sets up Protocol for when a channel already exists. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) - .build(); - - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) - .build(); - - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); - - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - - //Assures that the channel has a succeeded connectionFuture. - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, ""); + //setup + setupExistingProtocol(); + setupSteps(); + setupChannel(); + setupExistingChannelToken(); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message through the EmbeddedChannel - // pipeline + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); - Object msg = channel.readOutbound(); - - while (msg == null) { - msg = channel.readOutbound(); - } //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf) channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked - // as a success - verify(dummyStep, times(1)).accept(any(Token.class)); + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); } } From 57a88990f4e8294c61c9f2adcaf37bd530515f57 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 246/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From ee691847c78c6fc83f5a3055b1c83366959cfb1d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:54:13 -0400 Subject: [PATCH 247/337] Updated WebWhois tests. --- .../blackbox/ProbingActionTest.java | 56 +++--- .../blackbox/ProbingSequenceTest.java | 183 ++++++++++++++++++ .../monitoring/blackbox/ProbingStepTest.java | 3 +- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 93 +++++++-- .../monitoring/blackbox/TokenTest.java | 13 +- .../blackbox/handlers/ConversionHandler.java | 2 +- .../blackbox/handlers/NettyRule.java | 12 +- .../handlers/SslClientInitializerTest.java | 46 ++--- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 159 ++++++++------- 11 files changed, 422 insertions(+), 157 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index cbcf2fc82b0..162044c2036 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -83,31 +84,31 @@ public class ProbingActionTest { /** Sets up a {@link Protocol} corresponding to when a new connection is created */ private void setupNewChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(false) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) .build(); } /** Sets up a {@link Protocol} corresponding to when a new connection exists */ private void setupExistingChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(true) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(true) .build(); } - /** Sets up a {@link NewChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ private void setupNewChannelAction() { - newChannelAction = NewChannelAction.builder() - .bootstrap(bootstrap) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") - .address(address) + newChannelAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") + .setAddress(address) .build(); } @@ -115,25 +116,25 @@ private void setupChannel() { channel = new EmbeddedChannel(); } - /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ExistingChannelAction.builder() - .channel(channel) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") + existingChannelAction = ProbingAction.builder() + .setChannel(channel) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") .build(); } @Test - public void testBehavior_existingChannel() { + public void testBehavior_existingChannel() throws InternalException { //setup setupChannel(); setupExistingChannelProtocol(); - setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); + setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -147,6 +148,7 @@ public void testBehavior_existingChannel() { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -156,9 +158,9 @@ public void testBehavior_existingChannel() { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - setupNewChannelAction(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + setupNewChannelAction(); ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2b0559514a2..681a5346d55 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,5 +1,188 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; + +import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; +import java.net.SocketAddress; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) public class ProbingSequenceTest { + private final static String TEST_HOST = "TEST_HOST"; + + + private Bootstrap dummyBootstrap = new Bootstrap(); + private Token testToken = new ProbingSequenceTestToken(); + + /** + * Custom {@link ProbingStep} subclass that acts as a mock + * step, so we can test how well {@link ProbingSequence} builds + * a linked list of {@link ProbingStep}s from their {@link Builder}s. + */ + private static class TestStep extends ProbingStep { + private Bootstrap bootstrap; + private String marker; + + /** We implement all abstract methods to simply return null, as we have no use for them here. */ + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + SocketAddress address() { + return null; + } + + /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + /** + * Builder for {@link TestStep}, that extends {@link ProbingStep.Builder} so that these can be + * input into the {@link ProbingSequence.Builder}. + */ + public static class Builder extends ProbingStep.Builder { + /** We test to see if we accurately add the right bootstrap to all {@link ProbingStep}s/ */ + private Bootstrap bootstrap; + + /** We also mark each step in order to ensure that when running, they are arranged in the right order. */ + private String marker; + + @Override + public ProbingStep.Builder setDuration(Duration value) { + return this; + } + + @Override + public ProbingStep.Builder setProtocol(Protocol value) { + return this; + } + + @Override + public ProbingStep.Builder setMessageTemplate(OutboundMessageType value) { + return null; + } + + @Override + public ProbingStep.Builder setAddress(SocketAddress address) { + return null; + } + + @Override + public ProbingStep.Builder setBootstrap(Bootstrap value) { + bootstrap = value; + return this; + } + + public ProbingStep.Builder addMarker(String value) { + marker = value; + return this; + } + + @Override + public ProbingStep build() { + return new TestStep(bootstrap, marker); + } + } + private TestStep(Bootstrap bootstrap, String marker) { + this.bootstrap = bootstrap; + this.marker = marker; + } + + /** + * On a call to accept, we modify the token to reflect what the current step is, so we can get + * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated + * in order. + */ + @Override + public void accept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + if (!isLastStep) { + nextStep().accept(token); + } else { + ((TestStep)nextStep()).specialAccept(token); + } + } + + /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ + public void specialAccept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + return; + } + } + + @Test + public void testSequenceBasicConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("firstsecondthirdfirst"); + } + + @Test + public void testSequenceAdvancedConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(thirdStepBuilder) + .addStep(secondStepBuilder) + .markFirstRepeated() + .addStep(firstStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("thirdsecondfirstsecond"); + } + @Test + public void testSequenceConstruction_Failure() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + assertThrows(AssertionError.class, () -> { + ProbingSequence sequence = new ProbingSequence.Builder() + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .setBootstrap(dummyBootstrap) + .build(); + }); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 090753014e4..ee38e7cdf74 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -21,7 +21,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; @@ -47,7 +46,7 @@ import org.junit.Test; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { +public class ProbingStepTest { /** Basic Constants necessary for tests */ private final String ADDRESS_NAME = "TEST_ADDRESS"; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index ab9997b6c68..e833c717131 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -79,11 +79,11 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 8d1722c9625..161304c1f04 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,9 +17,11 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -37,6 +39,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; +import java.net.Socket; +import java.net.SocketAddress; +import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -141,26 +146,67 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } + + @Override + public OutboundMessageType modifyMessage(String... args) throws InternalException { + message = args[0]; + return this; + } + + @Override + public String name() { + return "Test Message of: " + this.toString(); + } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static class TestStep extends ProbingStep { + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .setAddress(address) + .build(); - public TestStep(Protocol protocol, String testMessage, LocalAddress address) { - super(protocol, new DuplexMessageTest(testMessage)); - this.address = address; - this.duration = Duration.ZERO; - } + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { - super(protocol, new DuplexMessageTest()); - future = new DefaultPromise(eventLoopGroup.next()) {}; - duration = Duration.ZERO; + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; + } + + @Nullable + @Override + SocketAddress address() { + return null; } @Override @@ -170,11 +216,16 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } + + @Override + public String toString() { + return "Dummy Step"; + } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - private String host; + protected String host; protected TestToken(String host) { this.host = host; @@ -221,6 +272,22 @@ public Channel channel() { } } + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..67963805733 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,10 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; @@ -34,20 +35,20 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..a8506a996a9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -37,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b6b5e8fbe0c..b38c1911940 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; @@ -89,7 +90,8 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - ProbingAction probingAction, + Protocol protocol, + String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -109,7 +111,9 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROBING_ACTION_KEY, probingAction); + .attr(PROTOCOL_KEY, protocol) + .attr(REMOTE_ADDRESS_KEY, host); + channel = b.connect(localAddress).syncUninterruptibly().channel(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 469c62a8f75..83c8e132f07 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,17 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ExistingChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; @@ -45,7 +46,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; -import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,8 +67,6 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); - /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -93,15 +91,12 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .persistentConnection(false) - .build(); - - private ProbingAction probingAction; + private final static Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -113,23 +108,13 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } - private void setupProbingAction(Channel channel) { - probingAction = ExistingChannelAction.builder() - .delay(Duration.ZERO) - .host(SSL_HOST) - .channel(channel) - .outboundMessage(DEFAULT_MESSAGE) - .protocol(PROTOCOL) - .build(); - } - @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - setupProbingAction(channel); - channel.attr(PROBING_ACTION_KEY).set(probingAction); + channel.attr(PROTOCOL_KEY).set(PROTOCOL); + channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -160,8 +145,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -189,8 +173,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -219,8 +202,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 518bb9ba686..e170fad8b8c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox.handlers; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index d8a672758da..72d5d5078df 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,21 +15,21 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; @@ -65,6 +65,14 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); + private static final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of()) + .setName("test_protocol") + .setPersistentConnection(false) + .setPort(HTTPS_PORT) + .build(); + private LocalAddress address; private EmbeddedChannel channel; @@ -75,30 +83,38 @@ public class WebWhoisActionHandlerTest { private void generateLocalAddress() { address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); } + /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port) { + private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of(actionHandlerProvider)) - .persistentConnection(false) + .setName(name) + .setPort(port) + .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) + .setPersistentConnection(persistentConnection) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); + private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { + actionHandler = new WebWhoisActionHandler( + bootstrap, + STANDARD_PROTOCOL, + STANDARD_PROTOCOL, + messageTemplate, + 80, + 443 + ); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); setupProbingActionBasic( protocol, outboundMessage, makeBootstrap(new NioEventLoopGroup(1))); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROBING_ACTION_KEY).set(probingAction); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -108,24 +124,25 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { } /**Sets up probingAction for when testing redirection */ private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(TARGET_HOST) - .address(DEFAULT_ADDRESS) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(TARGET_HOST) + .setAddress(DEFAULT_ADDRESS) + .setChannel(channel) .build(); } private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(host) - .address(address) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(host) + .setAddress(address) .build(); } @@ -136,10 +153,13 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, true); generateLocalAddress(); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + + setupChannel(initialProtocol, msg); //stores future @@ -151,7 +171,7 @@ public void testBasic_responseOk() throws Exception { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -161,15 +181,16 @@ public void testBasic_responseOk() throws Exception { //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseBad", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseBad", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -181,8 +202,7 @@ public void testBasic_responseFailure() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage - .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -194,14 +214,15 @@ public void testBasic_responseFailure() { assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseError() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseError", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseError", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -213,7 +234,7 @@ public void testBasic_responseError() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -224,27 +245,30 @@ public void testBasic_responseError() { assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_redirectCloseChannel() { //setup - HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", 0); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", 0, true); generateLocalAddress(); - setupChannel(initialProtocol, outboundMessage); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(outboundMessage); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -260,12 +284,15 @@ public void testBasic_redirectCloseChannel() { @Test public void testBasic_redirectHost() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); generateLocalAddress(); setupChannel(initialProtocol, msg); - HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); //store future @@ -275,27 +302,24 @@ public void testBasic_redirectHost() { channel.writeInbound(originalResponse); - ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - //gets changed protocol - Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); - assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); } @Test - public void testAdvanced_responseOk() { + public void testAdvanced_responseOk() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); //stores future ChannelFuture future = probingAction.call(); @@ -305,15 +329,16 @@ public void testAdvanced_responseOk() { } @Test - public void testAdvanced_responseFailure() { + public void testAdvanced_responseFailure() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); //stores future ChannelFuture future = probingAction.call(); From 9cae7e7e42c60ab9b41145d71f9c2c4b6f73dd18 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 248/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- prober/.gitignore | 2 +- .../registry/monitoring/blackbox/Prober.java | 9 +- .../monitoring/blackbox/ProberModule.java | 15 ++- .../monitoring/blackbox/ProbingAction.java | 96 +++++++-------- .../monitoring/blackbox/ProbingSequence.java | 24 +--- .../monitoring/blackbox/ProbingStep.java | 55 ++++++--- .../monitoring/blackbox/Protocol.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 49 ++++---- .../exceptions/ConnectionException.java | 5 +- .../blackbox/exceptions/FailureException.java | 15 ++- .../exceptions/InternalException.java | 30 ----- .../exceptions/ResponseException.java | 29 ----- .../UndeterminedStateException.java | 5 +- .../blackbox/handlers/ActionHandler.java | 94 +++------------ .../handlers/WebWhoisActionHandler.java | 51 ++++---- .../blackbox/messages/HttpRequestMessage.java | 4 +- .../messages/HttpResponseMessage.java | 6 +- .../messages/OutboundMessageType.java | 7 +- .../monitoring/blackbox/tokens/Token.java | 20 +-- .../blackbox/tokens/WebWhoisToken.java | 32 +++-- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../blackbox/ProbingActionTest.java | 9 +- .../blackbox/ProbingSequenceTest.java | 114 +++--------------- .../monitoring/blackbox/ProbingStepTest.java | 4 +- .../monitoring/blackbox/TestUtils.java | 21 +--- .../monitoring/blackbox/TokenTest.java | 8 +- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 106 +++++----------- 32 files changed, 294 insertions(+), 528 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/.gitignore b/prober/.gitignore index c86568e7672..77b1e2de2de 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 63a43ad4537..139aed1e49d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,10 +29,12 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 0daaf16ded4..1db97d1b581 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,14 +14,18 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.Set; import javax.inject.Singleton; import org.joda.time.Duration; @@ -33,7 +37,7 @@ public class ProberModule { /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = new Duration(4000L); + private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @@ -42,6 +46,12 @@ EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + @Provides + @Singleton + Class provideChannelClass() { + return NioSocketChannel.class; + } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides @Singleton @@ -51,6 +61,7 @@ Duration provideDuration() { /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides + @Singleton static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; @@ -66,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); + Set provideAllSequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 3f6a962b12d..67494dd5f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,25 +14,29 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -65,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -80,31 +87,18 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - @Nullable - public abstract SocketAddress address(); - - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { // Write appropriate outboundMessage to pipeline ChannelFuture channelFuture = actionHandler.getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> actionHandler.resetFuture(), - //inform ProbingStep of the status of our action future -> { if (future.isSuccess()) @@ -141,7 +135,7 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -154,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -180,19 +174,24 @@ public ChannelFuture performAction() throws InternalException { /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -210,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -221,40 +226,30 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract SocketAddress address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (address() == null) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + System.out.println("test"); + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -268,14 +263,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -293,7 +285,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2dbf48256f9..91c4165c068 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -49,32 +49,18 @@ public static class Builder { private ProbingStep currentStep; private ProbingStep firstStep; private ProbingStep firstRepeatedStep; - private Bootstrap bootstrap; - private Token startToken; - /** - * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. - * - *

Must be called before adding {@link ProbingStep.Builder}s.

- */ - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } + private Token startToken; - /** Adds start token that activate {@link ProbingSequence}. */ - public Builder addToken(Token token) { - startToken = token; - return this; + public Builder(Token startToken) { + this.startToken = startToken; } /** - * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, * built, and pointed to by the previous {@link ProbingStep} added. */ - public Builder addStep(ProbingStep.Builder stepBuilder) { - assert (bootstrap != null); - ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + public Builder addStep(ProbingStep step) { if (currentStep == null) firstStep = step; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 47c89c72c11..ca980100067 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import java.net.SocketAddress; import java.util.function.Consumer; -import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -39,18 +37,23 @@ @AutoValue public abstract class ProbingStep implements Consumer { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ - private boolean isLastStep = false; + protected boolean isLastStep = false; private ProbingStep nextStep; + /** Time delay duration between actions. */ abstract Duration duration(); + + /** {@link Protocol} type for this step. */ abstract Protocol protocol(); + + /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ abstract OutboundMessageType messageTemplate(); + + /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ abstract Bootstrap bootstrap(); - @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -63,8 +66,6 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); - public abstract Builder setAddress(SocketAddress address); - public abstract ProbingStep build(); } @@ -85,18 +86,18 @@ ProbingStep nextStep() { } /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws InternalException { + private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) .setProtocol(protocol()) .setOutboundMessage(message) - .setHost(token.getHost()) - .setBootstrap(bootstrap()) - .setAddress(address()); + .setHost(token.host()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); + else + probingActionBuilder.setBootstrap(bootstrap()); return probingActionBuilder.build(); } @@ -107,44 +108,58 @@ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } + /** + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. + * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

+ */ @Override public void accept(Token token) { ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - //call the created action ChannelFuture future; - try { + //call the generated action future = currentAction.call(); - - } catch(InternalException e) { + } catch(UndeterminedStateException e) { + //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); + + //Move on to next step in ProbingSequence nextStep.accept(generateNextToken(token)); return; } - //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - //If the next step maintains the connection, pass on the channel from this + } else { + //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 2f4a9342337..64e059407de 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -29,7 +29,7 @@ public abstract class Protocol { /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - abstract String name(); + public abstract String name(); public abstract int port(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index f9e9edfc6ad..fd55835856c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,6 +18,7 @@ import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,6 +27,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; @@ -44,11 +46,10 @@ @Module public class WebWhoisModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - private static final String DOMAIN_PREFIX = "whois.nic."; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; + private static final String HTTP_PROTOCOL_NAME = "http"; + private static final String HTTPS_PROTOCOL_NAME = "https"; /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; @@ -68,16 +69,14 @@ public class WebWhoisModule { /** {@link Provides} standard WebWhois sequence. */ @Provides - @WebWhoisProtocol + @Singleton + @IntoSet ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, - WebWhoisToken webWhoisToken, - @WebWhoisProtocol Bootstrap bootstrap) { + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { - return new ProbingSequence.Builder() - .addToken(webWhoisToken) - .setBootstrap(bootstrap) - .addStep(probingStepBuilder) + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) .build(); } @@ -85,15 +84,18 @@ ProbingSequence provideWebWhoisSequence( /** {@link Provides} only step used in WebWhois sequence. */ @Provides @WebWhoisProtocol - static ProbingStep.Builder provideWebWhoisStepBuilder( + static ProbingStep provideWebWhoisStep( @HttpWhoisProtocol Protocol httpWhoisProtocol, + @WebWhoisProtocol Bootstrap bootstrap, HttpRequestMessage messageTemplate, Duration duration) { return ProbingStep.builder() .setProtocol(httpWhoisProtocol) + .setBootstrap(bootstrap) .setMessageTemplate(messageTemplate) - .setDuration(duration); + .setDuration(duration) + .build(); } /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @@ -126,13 +128,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** {@link Provides} the prefix where we probe: "prefix.tld". */ - @Provides - @Named("Web-WHOIS-Prefix") - String provideWhoisPrefix() { - return DOMAIN_PREFIX; - } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @@ -187,10 +182,12 @@ static SslClientInitializer provideSslClientInitializer(SslPro @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + static Bootstrap provideBootstrap( + EventLoopGroup eventLoopGroup, + Class channelClass){ return new Bootstrap() .group(eventLoopGroup) - .channel(NioSocketChannel.class); + .channel(channelClass); } @Provides @@ -210,13 +207,13 @@ ImmutableList provideTopLevelDomains() { @Provides @HttpWhoisProtocol int provideHttpWhoisPort() { - return httpWhoIsPort; + return HTTP_WHOIS_PORT; } @Provides @HttpsWhoisProtocol int provideHttpsWhoisPort() { - return httpsWhoIsPort; + return HTTPS_WHOIS_PORT; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index be3d725c833..adb833ec629 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,9 +15,10 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is ERROR. + * Subclass of {@link UndeterminedStateException} that represents all instances when + * the action performed failed due to an issue in the connection with the server. */ -public class ConnectionException extends Exception { +public class ConnectionException extends UndeterminedStateException { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 9f716bb2589..36687e7ac82 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,5 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.exceptions; +/** + * Base exception class for all instances when the status of the action performed is FAILURE. + */ +public class FailureException extends Exception { + + public FailureException(String msg) { + super(msg); + } + + public FailureException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java index d7127717d52..c155d695c7f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java @@ -15,8 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails before we can determine - * the state of the result, meaning the status is recorded as ERROR. + * Base exception class for all instances when the action performed fails + * before we can determine the state of the result, meaning the status + * is recorded as ERROR. */ public class UndeterminedStateException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index e397393b4e9..0c9e93cc6dd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,13 +14,11 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -33,7 +31,7 @@ * messages that implement the {@link InboundMessageType} interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

@@ -44,111 +42,59 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); - - } else if (cause instanceof InternalException){ - //For an internal error, metrics should not be collected, so we log what caused this, and - //inform the ProbingStep the Prober had an internal error on this action - logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - - //As this was an internal error, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } else { - //In the case of any other kind of error, we assume it is some type of connection ERROR, - //so we treat it as such: + //On UndeterminedStateException, we know the response type is an error. - status = ResponseType.ERROR; - - logger.atInfo().log(cause.getMessage()); - finished.setSuccess(); + //Since it wasn't a success, we still log what caused the ERROR + logger.atWarning().log(cause.getMessage()); + finished.setFailure(cause); + //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - } - - /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ - @VisibleForTesting - ResponseType getStatus() { - return status; - } -} - +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 69d5b7f1603..1ec4e314813 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -22,13 +22,12 @@ import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -62,27 +61,17 @@ public class WebWhoisActionHandler extends ActionHandler { /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ private final HttpRequestMessage requestMessage; - /** Default port for http. */ - private int httpPort; - - /** default port for https. */ - private int httpsPort; - @Inject public WebWhoisActionHandler( @WebWhoisProtocol Bootstrap bootstrap, @HttpWhoisProtocol Protocol httpWhoisProtocol, @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage, - @HttpWhoisProtocol int httpPort, - @HttpsWhoisProtocol int httpsPort) { + HttpRequestMessage requestMessage) { this.bootstrap = bootstrap; this.httpWhoisProtocol = httpWhoisProtocol; this.httpsWhoisProtocol = httpsWhoisProtocol; this.requestMessage = requestMessage; - this.httpPort = httpPort; - this.httpsPort = httpsPort; } @@ -93,7 +82,7 @@ public WebWhoisActionHandler( */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -112,7 +101,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -123,12 +112,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; - if (newPort == httpPort) { + if (url.getProtocol().equals(httpWhoisProtocol.name())) { newProtocol = httpWhoisProtocol; - } else if (newPort == httpsPort) { + } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -143,34 +132,38 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) .setHost(newHost) .build(); - //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); - //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..b4c01d06a8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,12 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..f1b2d6ac6a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -25,11 +25,7 @@ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { - super(version, status); - } - - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index be6c872cc3e..6e3da3f69d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,7 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline @@ -22,8 +22,9 @@ public interface OutboundMessageType { /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - public OutboundMessageType modifyMessage(String... args) throws InternalException; + OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - public String name(); + @Override + String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dd1882b5686..dab5851e8d8 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,16 +14,18 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.ProbingSequence; +import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} - * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} + * in a single loop of a {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes + * in a {@link ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -31,17 +33,21 @@ */ public abstract class Token { - /** {@link Channel} that always starts out as null. */ + /** + * {@link Channel} that always starts out as null. Once a persistent connection + * is made (such as EPP), that channel is stored in the token and passed on to + * later steps in the sequence until a new loop begins. + */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String getHost(); + public abstract String host(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 2847e5ce0eb..bb06ee89db6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import javax.inject.Inject; import javax.inject.Named; @@ -33,42 +33,38 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final String prefix; + private final static String PREFIX = "whois.nic."; /** {@link ImmutableList} of all top level domains to be probed. */ - private final ImmutableList topLevelDomains; + private final Iterator topLevelDomainsIterator; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private int domainsIndex; + private String currentDomain; @Inject - public WebWhoisToken( - @Named("Web-WHOIS-Prefix") String prefix, - @WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { - domainsIndex = 0; - this.prefix = prefix; - this.topLevelDomains = topLevelDomains; + topLevelDomainsIterator = topLevelDomains.iterator(); + currentDomain = topLevelDomainsIterator.next(); } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - domainsIndex += 1; - domainsIndex %= topLevelDomains.size(); + currentDomain = topLevelDomainsIterator.next(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { - return original.modifyMessage(getHost()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + return original.modifyMessage(host()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String getHost() { - return prefix + topLevelDomains.get(domainsIndex); + public String host() { + return PREFIX + currentDomain; } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( { - ProbingSequence sequence = new ProbingSequence.Builder() - .addStep(firstStepBuilder) - .addStep(secondStepBuilder) - .addStep(thirdStepBuilder) - .addToken(testToken) - .setBootstrap(dummyBootstrap) - .build(); - }); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index ee38e7cdf74..7bba9d66782 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.TestUtils.dummyStep; import static google.registry.monitoring.blackbox.TestUtils.testStep; import static google.registry.testing.JUnitBackports.assertThrows; @@ -90,7 +91,7 @@ public class ProbingStepTest { /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ private void setupNewChannelToken() { - testToken = new NewChannelToken(""); + testToken = new NewChannelToken(ADDRESS_NAME); } /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ @@ -101,6 +102,7 @@ private void setupExistingChannelToken() { /** Sets up an embedded channel to contain the two handlers we created already */ private void setupChannel() { channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 161304c1f04..68bdd0bcef0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,7 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,8 +26,6 @@ import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpMessage; @@ -39,7 +37,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; -import java.net.Socket; import java.net.SocketAddress; import javax.annotation.Nullable; import javax.inject.Provider; @@ -148,15 +145,10 @@ public String toString() { } @Override - public OutboundMessageType modifyMessage(String... args) throws InternalException { + public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { message = args[0]; return this; } - - @Override - public String name() { - return "Test Message of: " + this.toString(); - } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ @@ -166,7 +158,6 @@ public static ProbingStep testStep(Protocol protocol, String testMessage, Bootst .setDuration(Duration.ZERO) .setMessageTemplate(new DuplexMessageTest(testMessage)) .setBootstrap(bootstrap) - .setAddress(address) .build(); } @@ -203,12 +194,6 @@ Bootstrap bootstrap() { return null; } - @Nullable - @Override - SocketAddress address() { - return null; - } - @Override public void accept(Token token) { future.setSuccess(token); @@ -241,7 +226,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String getHost() { + public String host() { return host; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index 67963805733..295bb809a13 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -17,12 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -37,7 +35,7 @@ public class TokenTest { private static String TEST_STARTER = "starter"; private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { @@ -49,7 +47,7 @@ public void testWebToken_MessageModificationSuccess() { try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index e170fad8b8c..3ecbdcc0d06 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -29,7 +29,7 @@ public class TestActionHandler extends ActionHandler { @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 72d5d5078df..2483bd65b1f 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,21 +15,23 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; +import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; @@ -64,11 +66,9 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); private static final Protocol STANDARD_PROTOCOL = Protocol.builder() .setHandlerProviders(ImmutableList.of()) - .setName("test_protocol") + .setName("http") .setPersistentConnection(false) .setPort(HTTPS_PORT) .build(); @@ -80,8 +80,10 @@ public class WebWhoisActionHandlerTest { private ProbingAction probingAction; private Provider actionHandlerProvider; - private void generateLocalAddress() { - address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + private String generateLocalAddress(String addressString) { + String modifiedAddress = addressString + System.currentTimeMillis(); + address = new LocalAddress(modifiedAddress); + return modifiedAddress; } /** Creates default protocol with empty list of handlers and specified other inputs */ @@ -100,9 +102,7 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT bootstrap, STANDARD_PROTOCOL, STANDARD_PROTOCOL, - messageTemplate, - 80, - 443 + messageTemplate ); actionHandlerProvider = new TestProvider<>(actionHandler); } @@ -111,10 +111,8 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - setupProbingActionBasic( - protocol, - outboundMessage, - makeBootstrap(new NioEventLoopGroup(1))); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -123,26 +121,23 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } /**Sets up probingAction for when testing redirection */ - private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) .setHost(TARGET_HOST) - .setAddress(DEFAULT_ADDRESS) .setChannel(channel) .build(); } - private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) .setBootstrap(bootstrap) - .setHost(host) - .setAddress(address) + .setHost(addressString) .build(); } @@ -157,8 +152,6 @@ public void testBasic_responseOk() throws Exception { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseOk", 0, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); @@ -185,13 +178,12 @@ public void testBasic_responseOk() throws Exception { } @Test - public void testBasic_responseFailure() { + public void testBasic_responseFailure_badRequest() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseBad", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -211,19 +203,18 @@ public void testBasic_responseFailure() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testBasic_responseError() { + public void testBasic_responseFailure_badURL() { //setup Bootstrap bootstrap = null; HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("responseError", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -243,9 +234,9 @@ public void testBasic_responseError() { //assesses that listener is triggered, and event is success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException); } @Test @@ -257,7 +248,6 @@ public void testBasic_redirectCloseChannel() { HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); setupActionHandler(bootstrap, msg); Protocol initialProtocol = createProtocol("redirectHttp", 0, true); - generateLocalAddress(); setupChannel(initialProtocol, msg); //stores future @@ -282,44 +272,15 @@ public void testBasic_redirectCloseChannel() { } @Test - public void testBasic_redirectHost() { + public void testAdvanced_responseOk() throws UndeterminedStateException { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); - HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); - - - //store future - ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(msg); - - - channel.writeInbound(originalResponse); - - Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - - - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - } - - @Test - public void testAdvanced_responseOk() throws InternalException { - //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); + String host = generateLocalAddress(TARGET_HOST); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); @@ -329,22 +290,21 @@ public void testAdvanced_responseOk() throws InternalException { } @Test - public void testAdvanced_responseFailure() throws InternalException { + public void testAdvanced_responseFailure() throws UndeterminedStateException { //setup - Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); + String host = generateLocalAddress(TARGET_HOST); HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(bootstrap, msg); + setupActionHandler(null, msg); Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", host, group); + setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); //stores future ChannelFuture future = probingAction.call(); //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + assertThrows(FailureException.class, future::syncUninterruptibly); } } From f899771b3dc6a8fbecfa3a1d20689e0a1a2cdf10 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:48:33 -0400 Subject: [PATCH 249/337] SpotlessApply run to fix style issues --- prober/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index 77b1e2de2de..c86568e7672 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From 44a2dc972646e0b2a7c08bd8751633ce6622ea51 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:28:40 -0400 Subject: [PATCH 250/337] Added license header and newline where appropriate. --- prober/build.gradle | 1 + .../monitoring/blackbox/ProbingAction.java | 1 - .../blackbox/handlers/ActionHandler.java | 2 +- .../monitoring/blackbox/ProbingSequenceTest.java | 14 ++++++++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index bb3b59ce8d7..3652390d0ba 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -35,6 +35,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] + compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 67494dd5f78..a8740e21c20 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -240,7 +240,6 @@ public ProbingAction build() { InetAddress hostAddress = InetAddress.getByName(host()); address = new InetSocketAddress(hostAddress, protocol().port()); } catch (UnknownHostException e) { - System.out.println("test"); address = new LocalAddress(host()); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 0c9e93cc6dd..8a108b81006 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -97,4 +97,4 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } -} \ No newline at end of file +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2a8d5ebe233..8d9e45c6a66 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; From 8fa0b5fcc6823bf600bf54357e5346ce7d21fead Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 251/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/ProbingStepTest.java | 1 - .../blackbox/TestServers/WebWhoisServer.java | 3 +- .../monitoring/blackbox/TestUtils.java | 35 +------------------ .../blackbox/handlers/ConversionHandler.java | 5 ++- .../blackbox/handlers/NettyRule.java | 4 ++- 5 files changed, 10 insertions(+), 38 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 7bba9d66782..73b104ae5dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -174,7 +174,6 @@ public void testNewChannel() throws Exception { //checks that when the future is successful, we pass down the requisite token assertThat(future.get()).isEqualTo(testToken); - } @Test diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index e833c717131..72ea4b2a284 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; @@ -66,7 +67,7 @@ static class RedirectHandler extends ChannelDuplexHandler { /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 68bdd0bcef0..cc8e1512fe9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; @@ -28,17 +27,13 @@ import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpMethod;; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; import java.net.SocketAddress; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -272,33 +267,5 @@ public void addToHost(String suffix) { } } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index a8506a996a9..196141bb875 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b38c1911940..1d14cf131e6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -26,6 +26,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.ProbingActionTest; +import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; @@ -54,7 +56,7 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { From 1b046a4a733a7cd63bb4d49addafc2497ec697d7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 5 Aug 2019 16:16:36 -0400 Subject: [PATCH 252/337] Refactored ProbingAction to minimize number of unnecessary methods --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 4 +- .../monitoring/blackbox/ProbingAction.java | 160 ++++++++---------- .../monitoring/blackbox/ProbingStep.java | 2 +- .../monitoring/blackbox/WebWhoisModule.java | 4 +- .../blackbox/handlers/ActionHandler.java | 2 +- .../handlers/WebWhoisActionHandler.java | 7 +- .../blackbox/messages/HttpRequestMessage.java | 5 +- .../blackbox/ProbingActionTest.java | 130 +++++++------- .../blackbox/ProbingSequenceTest.java | 25 ++- .../monitoring/blackbox/ProbingStepTest.java | 6 + .../monitoring/blackbox/TestUtils.java | 2 +- .../handlers/WebWhoisActionHandlerTest.java | 9 +- 13 files changed, 176 insertions(+), 183 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 139aed1e49d..dd412561286 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; import java.util.Set; @@ -29,7 +30,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); + Set sequences = proberComponent.sequences(); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 1db97d1b581..fb83b236b69 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -49,7 +49,7 @@ EventLoopGroup provideEventLoopGroup() { /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides @Singleton - Class provideChannelClass() { + Class provideChannelClazz() { return NioSocketChannel.class; } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @@ -77,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - Set provideAllSequences(); + Set sequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index a8740e21c20..25c3a1c17d6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -33,10 +33,8 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -69,6 +67,8 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -85,6 +85,7 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ @@ -94,108 +95,89 @@ public abstract class ProbingAction implements Callable { public abstract String host(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } - /** - * The method that performs the work of the actual action. + * Performs the work of the actual action * - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ *

First, checks if channel is active by setting a listener to perform the bulk of the work + * when the connection future is successful.

+ * + *

Once the connection is successful, we establish which of the handlers in the pipeline is + * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when + * we receive an expected response from the server.

+ * + *

Next, we set a timer set to a specified delay. After the delay has passed, we send the + * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, + * we inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - - //ChannelPromise that we use to inform ProbingStep when we are finished. - ChannelPromise finished = channel().newPromise(); - - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - - return finished; - } /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws UndeterminedStateException { + public ChannelFuture call() { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); + + //Ensures channel has been set up with connection future as an attribute + checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + //When connection is established call super.call and set returned listener to success channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { + (ChannelFuture connectionFuture) -> { + if (connectionFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); + ActionHandler actionHandler; + try { + actionHandler = channel().pipeline().get(ActionHandler.class); + } catch (ClassCastException e) { + //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); + } + + ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> { + if (future.isSuccess()) { + finished.setSuccess(); + } else { + finished.setFailure(future.cause()); + } + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) { + logger.atInfo() + .log("Closed stale channel. Moving on to next ProbingStep"); + } else { + logger.atWarning() + .log( + "Could not close channel. Stale connection still exists."); + } + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); } else { //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( + logger.atSevere().withCause(connectionFuture.cause()).log( "Cannot connect to relay channel for %s channel: %s.", protocol().name(), this.channel()); ChannelFuture unusedFuture = channel().close(); @@ -228,7 +210,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract Protocol protocol(); - abstract Optional channel(); + abstract Channel channel(); abstract String host(); @@ -243,11 +225,11 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { + if (channel() == null) { bootstrap.handler( new ChannelInitializer() { @Override diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index ca980100067..3df536a9478 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -135,7 +135,7 @@ public void accept(Token token) { try { //call the generated action future = currentAction.call(); - } catch(UndeterminedStateException e) { + } catch(Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index fd55835856c..7d09a865e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -184,10 +184,10 @@ static SslClientInitializer provideSslClientInitializer(SslPro @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClass){ + Class channelClazz){ return new Bootstrap() .group(eventLoopGroup) - .channel(channelClass); + .channel(channelClazz); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 8a108b81006..55c9123e3a5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -46,7 +46,7 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler testHandlerProvider = new TestProvider<>(testHandler); private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - private ProbingAction newChannelAction; - private ProbingAction existingChannelAction; - private EmbeddedChannel channel; - private Protocol protocol; - /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** Sets up a {@link Protocol} corresponding to when a new connection is created */ - private void setupNewChannelProtocol() { - protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - } - /** Sets up a {@link Protocol} corresponding to when a new connection exists */ - private void setupExistingChannelProtocol() { - protocol = Protocol.builder() + + + + @Test + public void testBehavior_existingChannel() throws UndeterminedStateException { + //setup + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up a Protocol corresponding to when a connection exists. + Protocol protocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) .build(); - } - - /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ - private void setupNewChannelAction() { - newChannelAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - } - - private void setupChannel() { - channel = new EmbeddedChannel(); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ - private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ProbingAction.builder() + // Sets up a ProbingAction that creates a channel using test specified attributes. + ProbingAction action = ProbingAction.builder() .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) .setHost("") .build(); - } - - @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { - //setup - setupChannel(); - setupExistingChannelProtocol(); - channel.pipeline().addLast(conversionHandler); - channel.pipeline().addLast(testHandler); - setupExistingChannelAction(channel); + //tests main function of ProbingAction + ChannelFuture future = action.call(); - ChannelFuture future = existingChannelAction.call(); - - //Ensures that we pass in the right message to the channel and haven't marked the future as success yet - Object msg = channel.readOutbound(); + //Obtains the outboundMessage passed through pipeline after delay + Object msg = null; + while (msg == null) { + msg = channel.readOutbound(); + } + //tests the passed message is exactly what we expect assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - assertThat(response).isEqualTo(TEST_MESSAGE); - assertThat(future.isSuccess()).isFalse(); + String request = ((ByteBuf) msg).toString(UTF_8); + assertThat(request).isEqualTo(TEST_MESSAGE); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -158,18 +122,40 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { @Test public void testSuccess_newChannel() throws Exception { //setup - setupNewChannelProtocol(); + + LocalAddress address = new LocalAddress(ADDRESS_NAME); + Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + // Sets up a Protocol corresponding to when a new connection is created. + Protocol protocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) + .build(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - setupNewChannelAction(); - ChannelFuture future = newChannelAction.call(); + + // Sets up a ProbingAction with existing channel using test specified attributes. + ProbingAction action = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) + .build(); + + //tests main function of ProbingAction + ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.sync(); + future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()); + assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 8d9e45c6a66..e5f91a300d6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -18,27 +18,44 @@ import static google.registry.testing.JUnitBackports.assertThrows; import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.TestUtils.TestToken; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import java.net.SocketAddress; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; @RunWith(JUnit4.class) public class ProbingSequenceTest { private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new ProbingSequenceTestToken(); + private Token testToken = new TestToken("") { + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + }; + private void setupMock(ProbingStep mock, ProbingStep nextStep) { + Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + } /** * Custom {@link ProbingStep} subclass that acts as a mock * step, so we can test how well {@link ProbingSequence} builds * a linked list of {@link ProbingStep}s from their {@link Builder}s. */ + private static class TestStep extends ProbingStep { private String marker; @@ -92,9 +109,9 @@ public void specialAccept(Token token) { @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 73b104ae5dc..256eeb0b29d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -45,6 +45,7 @@ import javax.inject.Provider; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ public class ProbingStepTest { @@ -191,6 +192,11 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); + Object msg = channel.readOutbound(); + + while (msg == null) { + msg = channel.readOutbound(); + } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index cc8e1512fe9..ef9926a7620 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -204,7 +204,7 @@ public String toString() { } /** Basic outline for {@link Token} instances to be used in tests */ - private static abstract class TestToken extends Token { + static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 2483bd65b1f..5fa39b1da83 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -41,7 +41,6 @@ import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; import org.joda.time.Duration; @@ -156,7 +155,7 @@ public void testBasic_responseOk() throws Exception { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); @@ -187,7 +186,7 @@ public void testBasic_responseFailure_badRequest() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -218,7 +217,7 @@ public void testBasic_responseFailure_badURL() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -251,7 +250,7 @@ public void testBasic_redirectCloseChannel() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early From 53b6a7f474c242944d402175df62d554ad600687 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 15:45:32 -0400 Subject: [PATCH 253/337] Modified tests for WebWhois according to changes suggested by laijiang. --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 2 - .../monitoring/blackbox/ProbingAction.java | 1 - .../monitoring/blackbox/WebWhoisModule.java | 10 +- .../blackbox/ProbingActionTest.java | 20 +- .../blackbox/ProbingSequenceTest.java | 120 ++++------- .../monitoring/blackbox/ProbingStepTest.java | 187 ++++++++--------- .../blackbox/TestServers/TestServer.java | 38 ---- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 142 +------------ .../monitoring/blackbox/TokenTest.java | 59 ------ .../blackbox/handlers/ConversionHandler.java | 6 +- .../blackbox/handlers/NettyRule.java | 46 +++- .../handlers/SslClientInitializerTest.java | 5 - .../blackbox/handlers/TestActionHandler.java | 7 +- .../handlers/WebWhoisActionHandlerTest.java | 197 +++++++----------- .../blackbox/messages/TestMessage.java | 4 + .../blackbox/tokens/WebWhoisTokenTest.java | 2 + 18 files changed, 266 insertions(+), 589 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index dd412561286..96cf3d97819 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -30,7 +29,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.sequences(); + ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index fb83b236b69..f9db4865f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,11 +14,9 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 25c3a1c17d6..0265390fafe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -138,7 +138,6 @@ public ChannelFuture call() { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); timer.newTimeout(timeout -> { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 7d09a865e5e..1af4145bb10 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,14 +17,11 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -33,10 +30,7 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index b5d8f7599c4..ec5ee5d77ec 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,17 +20,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -39,9 +37,9 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; import javax.inject.Provider; import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,10 +72,9 @@ public class ProbingActionTest { public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - + @Ignore @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { + public void testBehavior_existingChannel() { //setup EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -95,7 +92,7 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost("") .build(); @@ -112,6 +109,9 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { String request = ((ByteBuf) msg).toString(UTF_8); assertThat(request).isEqualTo(TEST_MESSAGE); + // Ensures that we haven't marked future as done until response is received. + assertThat(future.isDone()).isFalse(); + //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); assertThat(future.isSuccess()).isTrue(); @@ -143,7 +143,7 @@ public void testSuccess_newChannel() throws Exception { .setBootstrap(bootstrap) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost(ADDRESS_NAME) .build(); @@ -151,7 +151,7 @@ public void testSuccess_newChannel() throws Exception { ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index e5f91a300d6..5c4452df7b3 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -15,17 +15,11 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; -import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; -import google.registry.monitoring.blackbox.TestUtils.TestToken; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import java.net.SocketAddress; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,85 +27,31 @@ @RunWith(JUnit4.class) public class ProbingSequenceTest { - private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new TestToken("") { - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - }; - - private void setupMock(ProbingStep mock, ProbingStep nextStep) { - Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + private ProbingStep setupMock() { + ProbingStep mock = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(mock).nextStep(); + return mock; } - /** - * Custom {@link ProbingStep} subclass that acts as a mock - * step, so we can test how well {@link ProbingSequence} builds - * a linked list of {@link ProbingStep}s from their {@link Builder}s. - */ - - private static class TestStep extends ProbingStep { - private String marker; - - /** We implement all abstract methods to simply return null, as we have no use for them here. */ - @Override - Duration duration() { - return null; - } - @Override - Protocol protocol() { - return null; - } + private static class Wrapper { - @Override - OutboundMessageType messageTemplate() { - return null; - } + T data; - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ - @Override - Bootstrap bootstrap() { - return null; - } - - public TestStep(String marker) { - this.marker = marker; - } - - /** - * On a call to accept, we modify the token to reflect what the current step is, so we can get - * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated - * in order. - */ - @Override - public void accept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - if (!isLastStep) { - nextStep().accept(token); - } else { - ((TestStep)nextStep()).specialAccept(token); - } - } - - /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ - public void specialAccept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - return; + public Wrapper(T data) { + this.data = data; } } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = Mockito.mock(ProbingStep.class); - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) @@ -119,16 +59,25 @@ public void testSequenceBasicConstruction_Success() { .addStep(thirdStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(thirdStep); + assertThat(thirdStep.nextStep()).isEqualTo(firstStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); + assertThat(wrapper.data).isTrue(); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(thirdStep) @@ -137,9 +86,16 @@ public void testSequenceAdvancedConstruction_Success() { .addStep(firstStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(firstStep); + assertThat(thirdStep.nextStep()).isEqualTo(secondStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); + assertThat(wrapper.data).isTrue(); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 256eeb0b29d..91a113940e8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,18 +11,19 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.TestUtils.dummyStep; -import static google.registry.monitoring.blackbox.TestUtils.testStep; -import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; import google.registry.monitoring.blackbox.TestUtils.TestProvider; @@ -30,19 +31,20 @@ import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; +import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; @@ -51,18 +53,18 @@ public class ProbingStepTest { /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final static String ADDRESS_NAME = "TEST_ADDRESS"; + private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final static int PROTOCOL_PORT = 0; + private final static String TEST_MESSAGE = "TEST_MESSAGE"; + private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -73,117 +75,108 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(ADDRESS_NAME); + /** + * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} + * is called, it just marks the supplied future as succeeded, returning the requisite token. + */ + private ProbingStep dummyStep() { + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(dummyStep).nextStep(); + return dummyStep; } - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); - dummyStep = dummyStep(eventLoopGroup); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - } + @Test + public void testNewChannel() throws Exception { + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() + // Sets up Protocol for when we create a new channel. + Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); - } - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) .build(); - } - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - //there should be no next step - assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); - } + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); - @Test - public void testNewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + //Set up blackbox server that receives our messages then echoes them back to us + nettyRule.setUpServer(address); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); + verify(dummyStep, times(1)).accept(any(Token.class)); } + @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupChannel(); - setupExistingChannelToken(); + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); + + // Sets up Protocol for when a channel already exists. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) + .build(); + + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) + .build(); + + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + + // Sets up an embedded channel to contain the two handlers we created already. + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + + //Assures that the channel has a succeeded connectionFuture. + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. + Token testToken = new ExistingChannelToken(channel, ""); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -200,17 +193,13 @@ public void testWithSequence_ExistingChannel() throws Exception { //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); + //At this point, we should have received the message, so the future obtained should be marked + // as a success + verify(dummyStep, times(1)).accept(any(Token.class)); - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 67e2cb7165d..a786f7ba791 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,23 +1,15 @@ package google.registry.monitoring.blackbox.TestServers; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; - import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; /** * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform @@ -51,35 +43,5 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 72ea4b2a284..a90ed987359 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -11,6 +11,7 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -60,7 +61,7 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends ChannelDuplexHandler { + static class RedirectHandler extends SimpleChannelInboundHandler { private String redirectInput; private String destinationInput; @@ -76,8 +77,7 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - HttpRequest request = (HttpRequest) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index ef9926a7620..2567a7cc155 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,42 +16,24 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMethod;; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.concurrent.DefaultPromise; -import java.net.SocketAddress; import javax.inject.Provider; -import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { - static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -76,33 +58,13 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); + response.headers().set("content-type", "text/plain"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); return response; } @@ -121,88 +83,6 @@ public E get() { } } - /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ - public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { - - String message; - - public DuplexMessageTest() { - message = ""; - } - - public DuplexMessageTest(String msg) { - message = msg; - } - - @Override - public String toString() { - return message; - } - - @Override - public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { - message = args[0]; - return this; - } - } - - /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .build(); - - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); - } - - /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { - private DefaultPromise future; - - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; - } - - @Override - public void accept(Token token) { - future.setSuccess(token); - } - public DefaultPromise getFuture() { - return future; - } - - @Override - public String toString() { - return "Dummy Step"; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; @@ -251,21 +131,5 @@ public Channel channel() { return channel; } } - - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java deleted file mode 100644 index 295bb809a13..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) - */ -@RunWith(JUnit4.class) -public class TokenTest { - - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - - public Token webToken = new WebWhoisToken(TEST_DOMAINS); - - @Test - public void testWebToken_MessageModificationSuccess() { - //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); - - //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { - throw new RuntimeException(e); - } - - - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 196141bb875..c9d337d6ad8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -32,7 +32,7 @@ * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +40,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 1d14cf131e6..86b54d9a07d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -25,14 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -44,7 +41,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -55,7 +51,7 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + *

Code based on and almost identical to {@code NettyRule} in the proxy. * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -83,10 +79,12 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + ImmutableList.builder().add(handlers).add(echoHandler).build()); } /** Sets up a client channel connecting to the give local address. */ @@ -124,7 +122,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertThatCustomWorks(String message) throws Exception { + public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -165,6 +163,38 @@ ThrowableSubject assertThatClientRootCause() { } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** + * Saves any inbound error as the cause of the promise failure. + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 83c8e132f07..523fb228752 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -22,12 +22,7 @@ import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 3ecbdcc0d06..95b06e623d1 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -25,17 +25,16 @@ */ public class TestActionHandler extends ActionHandler { - private String receivedMessage; + private InboundMessageType receivedMessage; @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage.toString(); + receivedMessage = inboundMessage; super.channelRead0(ctx, inboundMessage); } - @Override - public String toString() { + public InboundMessageType getResponse() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 5fa39b1da83..3667f3f3d9a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -20,7 +20,6 @@ import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; -import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; @@ -28,13 +27,11 @@ import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; @@ -56,6 +53,7 @@ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -65,11 +63,12 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of()) + private final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( + null, null, null, null)))) .setName("http") .setPersistentConnection(false) - .setPort(HTTPS_PORT) + .setPort(HTTP_PORT) .build(); @@ -78,14 +77,13 @@ public class WebWhoisActionHandlerTest { private ActionHandler actionHandler; private ProbingAction probingAction; private Provider actionHandlerProvider; + private Protocol initialProtocol; + private HttpRequestMessage msg; - private String generateLocalAddress(String addressString) { - String modifiedAddress = addressString + System.currentTimeMillis(); - address = new LocalAddress(modifiedAddress); - return modifiedAddress; - } - /** Creates default protocol with empty list of handlers and specified other inputs */ + /** + * Creates default protocol with empty list of handlers and specified other inputs + */ private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() .setName(name) @@ -95,7 +93,9 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect .build(); } - /** Initializes new WebWhoisActionHandler */ + /** + * Initializes new WebWhoisActionHandler + */ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, @@ -106,12 +106,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT actionHandlerProvider = new TestProvider<>(actionHandler); } - /** Sets up testing channel with requisite attributes */ + /** + * Sets up testing channel with requisite attributes + */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - setupProbingActionWithChannel(protocol, outboundMessage); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -119,18 +120,9 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .group(group) .channel(LocalChannel.class); } - /**Sets up probingAction for when testing redirection */ - private void setupProbingActionWithChannel(Protocol protocol, HttpRequestMessage outboundMessage) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setHost(TARGET_HOST) - .setChannel(channel) - .build(); - } - private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { + private void setupProbingActionWithoutChannel(Protocol protocol, + HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) @@ -140,171 +132,124 @@ private void setupProbingActionWithoutChannel(Protocol protocol, HttpRequestMess .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + private void setupLocalServer(String redirectInput, String destinationInput, + EventLoopGroup group) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testBasic_responseOk() throws Exception { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { + msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, true); + initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + } + + @Test + public void testBasic_responseOk() { + //setup + setup("", null, true); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure_badRequest() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseBad", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage( + makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same assertThat(future.cause() instanceof FailureException).isTrue(); } - @Test - public void testBasic_responseFailure_badURL() { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseError", 0, true); - setupChannel(initialProtocol, msg); - - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, and event is success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); - } @Test - public void testBasic_redirectCloseChannel() { + public void testBasic_responseFailure_badURL() { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", 0, true); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - //checks that future has not been set to successful or a failure - assertThat(testPromise.isSuccess()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - + //assesses that listener is triggered, and event is success + assertThat(future.isDone()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + //ensures Protocol is the same + assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_responseOk() throws UndeterminedStateException { - //setup + public void testAdvanced_redirect() { + // Sets up EventLoopGroup with 1 thread to be blocking. EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(host, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + // Sets up embedded channel. + setup("", makeBootstrap(group), false); + setupChannel(initialProtocol, msg); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); - } + // Initializes LocalAddress with unique String. + String host = TARGET_HOST + System.currentTimeMillis(); + address = new LocalAddress(host); - @Test - public void testAdvanced_responseFailure() throws UndeterminedStateException { - //setup - EventLoopGroup group = new NioEventLoopGroup(1); - String host = generateLocalAddress(TARGET_HOST); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(null, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); + //stores future + ChannelFuture future = actionHandler.getFinishedFuture(); + channel.writeOutbound(msg); + + // Sets up the local server that the handler will be redirected to. setupLocalServer("", host, group); - setupProbingActionWithoutChannel(initialProtocol, msg, makeBootstrap(group), host); - //stores future - ChannelFuture future = probingAction.call(); + FullHttpResponse response = + new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, + HTTP_REDIRECT + host, true, false)); + + //checks that future has not been set to successful or a failure + assertThat(future.isDone()).isFalse(); + + channel.writeInbound(response); + + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); //assesses that we successfully received good response and protocol is unchanged - assertThrows(FailureException.class, future::syncUninterruptibly); + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index 922c3052bda..c31a9d336bd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,6 +24,10 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; + public TestMessage() { + this(""); + } + public TestMessage(String msg) { message = msg; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index 9a3e755364b..bf5cfc45652 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -19,6 +19,8 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; From f93afbf5c4e00be28fb1a9a7398acc44f9208d9c Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 16:42:43 -0400 Subject: [PATCH 254/337] Removed TestProvider from TestUtils. --- .../blackbox/ProbingActionTest.java | 7 ++-- .../monitoring/blackbox/ProbingStepTest.java | 11 +++--- .../blackbox/TestServers/TestServer.java | 3 -- .../monitoring/blackbox/TestUtils.java | 17 --------- .../handlers/WebWhoisActionHandlerTest.java | 36 ++++++------------- .../blackbox/messages/TestMessage.java | 4 --- 6 files changed, 18 insertions(+), 60 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index ec5ee5d77ec..f7857dd80f9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -64,8 +63,8 @@ public class ProbingActionTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + private Provider testHandlerProvider = () -> testHandler; + private Provider conversionHandlerProvider = () -> conversionHandler; /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -156,7 +155,7 @@ public void testSuccess_newChannel() throws Exception { future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 91a113940e8..1f09dd13553 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -90,9 +89,8 @@ private ProbingStep dummyStep() { @Test public void testNewChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when we create a new channel. Protocol testProtocol = Protocol.builder() @@ -142,9 +140,8 @@ public void testNewChannel() throws Exception { @Test public void testWithSequence_ExistingChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when a channel already exists. Protocol testProtocol = Protocol.builder() diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index a786f7ba791..1da762b2c33 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -15,15 +15,12 @@ * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform */ public abstract class TestServer { - private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - this.localAddress = localAddress; - //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 2567a7cc155..50c60d9fc52 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -21,7 +21,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -29,7 +28,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Provider; /** Utility class for various helper methods used in testing. */ public class TestUtils { @@ -68,21 +66,6 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ - public static class TestProvider implements Provider { - - private E obj; - - public TestProvider(E obj) { - this.obj = obj; - } - - @Override - public E get() { - return obj; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 3667f3f3d9a..33eb190a66a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -25,7 +25,6 @@ import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; @@ -64,18 +63,16 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( - null, null, null, null)))) + .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( + null, null, null, null))) .setName("http") .setPersistentConnection(false) .setPort(HTTP_PORT) .build(); - private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; - private ProbingAction probingAction; private Provider actionHandlerProvider; private Protocol initialProtocol; private HttpRequestMessage msg; @@ -103,13 +100,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT STANDARD_PROTOCOL, messageTemplate ); - actionHandlerProvider = new TestProvider<>(actionHandler); + actionHandlerProvider = () -> actionHandler; } /** * Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + private void setupChannel(Protocol protocol) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -121,19 +118,8 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } - private void setupProbingActionWithoutChannel(Protocol protocol, - HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(addressString) - .build(); - } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group) { + EventLoopGroup group, LocalAddress address) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } @@ -148,7 +134,7 @@ private void setup(String hostName, Bootstrap bootstrap, boolean persistentConne public void testBasic_responseOk() { //setup setup("", null, true); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -169,7 +155,7 @@ public void testBasic_responseOk() { public void testBasic_responseFailure_badRequest() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -195,7 +181,7 @@ public void testBasic_responseFailure_badRequest() { public void testBasic_responseFailure_badURL() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -224,18 +210,18 @@ public void testAdvanced_redirect() { // Sets up embedded channel. setup("", makeBootstrap(group), false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); // Initializes LocalAddress with unique String. String host = TARGET_HOST + System.currentTimeMillis(); - address = new LocalAddress(host); + LocalAddress address = new LocalAddress(host); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group); + setupLocalServer("", host, group, address); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index c31a9d336bd..922c3052bda 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,10 +24,6 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; - public TestMessage() { - this(""); - } - public TestMessage(String msg) { message = msg; } From 0a4fbc59047292ccbede0fb5375fdaaa071c4185 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 255/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 2 +- .../google/registry/xjc/package-info.java | 2 +- prober/build.gradle | 5 - .../monitoring/blackbox/NewChannelAction.java | 136 +++++++++ .../registry/monitoring/blackbox/Prober.java | 19 +- .../monitoring/blackbox/ProbingAction.java | 265 ++++++------------ .../handlers/ServerSideException.java | 15 + .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 117 +++----- .../blackbox/messages/HttpRequestMessage.java | 63 +---- .../messages/HttpResponseMessage.java | 44 +-- .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 15 files changed, 320 insertions(+), 365 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/prober/build.gradle b/prober/build.gradle index 3652390d0ba..e1e1e1144b3 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -20,8 +20,6 @@ dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] @@ -33,9 +31,6 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..0ba3a0c22be --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 96cf3d97819..36377247fa5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,27 +14,18 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 0265390fafe..2441debb12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,27 +14,14 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -47,7 +34,7 @@ import javax.inject.Provider; /** - * AutoValue class that represents action generated by {@link ProbingStep} + *Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -57,27 +44,36 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

*/ -@AutoValue + public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + + + /** + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; + } /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); + /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -85,177 +81,92 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ - @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); - /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> finished.setSuccess(), + future -> { + if (!protocol().persistentConnection()) { + + //If we created a new channel for this action, close the connection to the channel + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } /** - * Performs the work of the actual action + * The method that sends the {@code outboundMessage} down the channel pipeline * - *

First, checks if channel is active by setting a listener to perform the bulk of the work - * when the connection future is successful.

- * - *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

- * - *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

- * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. + * @return future that denotes when the action has been successfully performed */ - - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override public ChannelFuture call() { - //ChannelPromise that we return - ChannelPromise finished = channel().newPromise(); - //Ensures channel has been set up with connection future as an attribute - checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); - - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture connectionFuture) -> { - if (connectionFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - - ActionHandler actionHandler; - try { - actionHandler = channel().pipeline().get(ActionHandler.class); - } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); - - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> { - if (future.isSuccess()) { - finished.setSuccess(); - } else { - finished.setFailure(future.cause()); - } - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) { - logger.atInfo() - .log("Closed stale channel. Moving on to next ProbingStep"); - } else { - logger.atWarning() - .log( - "Could not close channel. Stale connection still exists."); - } - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(connectionFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ - @AutoValue.Builder - public abstract static class Builder { - private Bootstrap bootstrap; - - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); } - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setHost(String value); - - public abstract Builder setChannel(Channel channel); - - abstract Protocol protocol(); + //ChannelPromise that we use to inform ProbingStep when we are finished. + ChannelPromise finished = channel().newPromise(); - abstract Channel channel(); + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } - abstract String host(); + return finished; + } - abstract ProbingAction autoBuild(); + public abstract static class Builder, P extends ProbingAction> { - public ProbingAction build() { - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - address = new LocalAddress(host()); - } + public abstract B delay(Duration value); - checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); - //If a channel is supplied, nothing is needed to be done + public abstract B outboundMessage(OutboundMessageType value); - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel() == null) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); + public abstract B protocol(Protocol value); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); + public abstract B host(String value); - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } + public abstract B path(String value); - //now we can actually build the ProbingAction - return autoBuild(); - } - } + public abstract P build(); - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); } /** @@ -265,27 +176,11 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - private static void addHandlers( + static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { channelPipeline.addLast(handlerProvider.get()); } } - - - - @Override - public String toString() { - return String.format( - "ProbingAction with delay: %d\n" + - "outboundMessage: %s\n" + - "protocol: %s\n" + - "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index 919006592ea..ac844ac99df 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,8 +15,7 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -90,8 +89,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - String host = channel.attr(REMOTE_ADDRESS_KEY).get(); + ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); + Protocol protocol = action.protocol(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -104,7 +103,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), host, protocol.port()); + .newHandler(channel.alloc(), action.host(), protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 34eac2a0118..21010f0e887 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,23 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -47,53 +48,30 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ - private final Bootstrap bootstrap; - - /** {@link Protocol} for when redirected to http endpoint. */ - private final Protocol httpWhoisProtocol; - - /** {@link Protocol} for when redirected to https endpoint. */ - private final Protocol httpsWhoisProtocol; - - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } + public WebWhoisActionHandler() {} /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { + throws ServerSideException { HttpResponseMessage response = (HttpResponseMessage) msg; + if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - //On success, we always pass message to ActionHandler's channelRead0 method. - super.channelRead0(ctx, msg); + finished.setSuccess(); + + logger.atInfo().log("Response Received: " + response); - } else if (response.headers().get("location") != null) { + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { //Obtain url to be redirected to URL url; @@ -101,68 +79,55 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); + int newPort = url.getDefaultPort(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, url.getDefaultPort(), newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException("Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); - } + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) .build(); + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } + logger.atInfo().log("Successfully Closed Connection"); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE + finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 5e9300d0f34..3fb8c187ad9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -19,28 +5,19 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; -/** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. - * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + @Override @@ -49,33 +26,15 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } - - /** Modifies headers to reflect new host and new path if applicable. */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) - setUri(args[1]); - - return this; + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + ByteBuf buf = request.content(); + if (buf == null) { + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - throw new IllegalArgumentException( - String.format( - "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + args, args.length)); + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - } - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index f1b2d6ac6a7..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,19 +6,33 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} - */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { + super(version, status); + } + + public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); + + return finalResponse; } + + + } diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From 199137e04e5895ea7690906b87e185d9a880e084 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:58:52 -0400 Subject: [PATCH 256/337] Fixed changes suggested by CydeWeys --- prober/build.gradle | 10 +- .../monitoring/blackbox/Protocol.java | 87 +++++-- .../blackbox/exceptions/FailureException.java | 15 +- .../blackbox/handlers/ActionHandler.java | 89 +++---- .../blackbox/messages/InboundMessageType.java | 8 +- .../handlers/WebWhoisActionHandlerTest.java | 224 ++++++++---------- 6 files changed, 212 insertions(+), 221 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index e1e1e1144b3..ae4bd27b731 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,10 +16,13 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] @@ -31,11 +34,13 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - + testCompile deps['com.google.truth:truth'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] @@ -48,3 +53,4 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 64e059407de..05af501ad5a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,56 +16,97 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; import io.netty.util.AttributeKey; +import io.netty.channel.ChannelHandler; import javax.inject.Provider; /** - * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. + * Protocol Class packages all static variables necessary for a certain type of connection + * Both the host and the path can be changed for the same protocol + * Mainly packages the handlers necessary for the requisite channel pipeline */ @AutoValue public abstract class Protocol { - /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ - public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); + + /** + * Default names associated with each protocol + */ + final static String EPP_PROTOCOL_NAME = "EPP"; + final static String DNS_PROTOCOL_NAME = "DNS"; + final static String WHOIS_PROTOCOL_NAME = "WHOIS"; + final static String RDAP_PROTOCOL_NAME = "RDAP"; + + private String host; + private String path = ""; + private ProbingAction probingAction; + + /** Setter method for Protocol's host*/ + public Protocol host(String host) { + this.host = host; + return this; + } + + /** Getter method for Protocol's host*/ + public String host() { + return host; + } + + /** Setter method for Protocol's path*/ + public Protocol path(String path) { + this.path = path; + return this; + } + + /** Getter method for Protocol's path*/ + public String path() { + return path; + } + /** Setter method for Protocol's ProbingAction parent*/ + public Protocol probingAction(ProbingAction probingAction) { + this.probingAction = probingAction; + return this; + } + + /** Getter method for Protocol's path*/ + public ProbingAction probingAction() { + return probingAction; + } + + /** If connection associated with Protocol is persistent, which is only EPP */ + public boolean persistentConnection() { + return name() == EPP_PROTOCOL_NAME; + } + + /** Protocol Name */ public abstract String name(); + /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - abstract ImmutableList> handlerProviders(); + public abstract ImmutableList> handlerProviders(); - /** Boolean that notes if connection associated with Protocol is persistent.*/ - abstract boolean persistentConnection(); + + public abstract Builder toBuilder(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } + @AutoValue.Builder public static abstract class Builder { - public abstract Builder setName(String value); - - public abstract Builder setPort(int num); + public abstract Builder name(String value); - public abstract Builder setHandlerProviders(ImmutableList> providers); + public abstract Builder port(int num); - public abstract Builder setPersistentConnection(boolean value); + public abstract Builder handlerProviders(ImmutableList> providers); public abstract Protocol build(); } - - @Override - public String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 36687e7ac82..9f716bb2589 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,18 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.exceptions; +package google.registry.monitoring.blackbox; -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class FailureException extends Exception { - - public FailureException(String msg) { - super(msg); - } - - public FailureException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 55c9123e3a5..3fa60cd844a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,86 +15,69 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; +import com.google.common.flogger.StackSize; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.HttpResponse; +import java.util.function.Function; +import javax.inject.Inject; /** - *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

- * - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} - * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

- * - *

Subclasses specify further work to be done for specific kinds of channel pipelines.

+ * @param Generic Type of Inbound Message + * @param Generic Type of Outbound Message + * Abstract class that tells sends message down pipeline and + * and tells listeners to move on when the message is received. */ -public abstract class ActionHandler extends SimpleChannelInboundHandler { +public abstract class ActionHandler extends SimpleChannelInboundHandler + implements Function { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link ChannelPromise} that informs {@link ProbingAction} if response has been received. */ - private ChannelPromise finished; + protected ChannelPromise finished; + private Channel channel; + - /** Returns initialized {@link ChannelPromise} to {@link ProbingAction}.*/ - public ChannelFuture getFinishedFuture() { + /** returns ChannelPromise for when inbound message is recieved + * a + * @param outboundMessage + * @return + */ + @Override + public ChannelFuture apply(O outboundMessage) { + // Sends request along Outbound Handlers on the Pipeline + + channel.writeAndFlush(outboundMessage); return finished; + + } + + public void resetFuture() { + finished = channel.newPromise(); } - /** Initializes {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler + + channel = ctx.channel(); finished = ctx.newPromise(); } - /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { + public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ + //Only purpose of Handler is to mark future as a success finished.setSuccess(); } - /** - * Logs the channel and pipeline that caused error, closes channel, then informs - * {@link ProbingAction} listeners of error. - */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atWarning().withCause(cause).log(String.format( - "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", - ctx.channel().toString(), - ctx.channel().pipeline().toString())); - - if (cause instanceof FailureException) { - //On FailureException, we know the response is a failure. - - //Since it wasn't a success, we still want to log to see what caused the FAILURE - logger.atInfo().log(cause.getMessage()); - - //As always, inform the ProbingStep that we successfully completed this action - finished.setFailure(cause); - - } else { - //On UndeterminedStateException, we know the response type is an error. - - //Since it wasn't a success, we still log what caused the ERROR - logger.atWarning().log(cause.getMessage()); - finished.setFailure(cause); - - //As this was an ERROR in performing the action, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } + logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 0c1260becf2..cb9c96f37f6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -12,10 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.messages; - -/** - * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline - */ -public interface InboundMessageType {} - +package google.registry.monitoring.blackbox; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 33eb190a66a..63bb2cf5b53 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,44 +15,34 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.ChannelPromise; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@link WebWhoisActionHandler}. - * - *

Attempts to test how well {@link WebWhoisActionHandler} works - * when responding to all possible types of responses

- */ +/** Unit tests for {@link WebWhoisActionHandler}. + * Attempts to test how well WebWhoIsActionHandler works + * when responding to all possible types of responses + * */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { - private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -60,182 +50,172 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; - private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( - null, null, null, null))) - .setName("http") - .setPersistentConnection(false) - .setPort(HTTP_PORT) - .build(); private EmbeddedChannel channel; private ActionHandler actionHandler; - private Provider actionHandlerProvider; - private Protocol initialProtocol; - private HttpRequestMessage msg; - - /** - * Creates default protocol with empty list of handlers and specified other inputs - */ - private Protocol createProtocol(String name, int port, boolean persistentConnection) { + /** Creates default protocol with empty list of handlers and specified other inputs */ + private Protocol createProtocol(String name, int port, String host) { return Protocol.builder() - .setName(name) - .setPort(port) - .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) - .setPersistentConnection(persistentConnection) - .build(); + .name(name) + .port(port) + .handlerProviders(ImmutableList.of()) + .build() + .host(host); } - /** - * Initializes new WebWhoisActionHandler - */ - private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { - actionHandler = new WebWhoisActionHandler( - bootstrap, - STANDARD_PROTOCOL, - STANDARD_PROTOCOL, - messageTemplate - ); - actionHandlerProvider = () -> actionHandler; + /** Initializes new WebWhoisActionHandler */ + private void setupActionHandler() { + actionHandler = new WebWhoisActionHandler(); } - /** - * Sets up testing channel with requisite attributes - */ + /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol) { + setupActionHandler(); channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } - private Bootstrap makeBootstrap(EventLoopGroup group) { - return new Bootstrap() - .group(group) - .channel(LocalChannel.class); + /**Sets up probingAction for when testing redirection */ + private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { + NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group, LocalAddress address) { - WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); + /** Sets up everything specified in above methods*/ + private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { + setupProbingAction( + protocol, + outboundMessage, + new Bootstrap() + .group(new NioEventLoopGroup()) + .channel(NioSocketChannel.class)); + setupChannel(protocol); } - private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { - msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); - setupActionHandler(bootstrap, msg); - initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + private static FullHttpResponse makeRedirectResponse( + HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + FullHttpResponse response = makeHttpResponse("", status); + response.headers().set("content-type", "text/plain").set("content-length", "0"); + if (location != null) { + response.headers().set("location", location); + } + if (keepAlive) { + response.headers().set("connection", "keep-alive"); + } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; } + @Test - public void testBasic_responseOk() { + public void testSuccess_responseOk() { //setup - setup("", null, true); + Protocol initialProtocol = createProtocol("responseOk", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); - //assesses that we successfully received good response and protocol is unchanged + //assesses that we successfully receivved good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badRequest() { + public void testSuccess_responseBad() { //setup - setup("", null, false); + Protocol initialProtocol = createProtocol("responseBad", 0, ""); setupChannel(initialProtocol); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage( - makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(future.isDone()).isTrue(); + assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException).isTrue(); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure_badURL() { + public void testSuccess_redirectCloseChannel() { //setup - setup("", null, false); - setupChannel(initialProtocol); + Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); + HttpRequest outboundMessage = makeHttpGetRequest("", ""); + setupChannelWithProbingAction(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + ChannelFuture future = actionHandler.apply(outboundMessage); - FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); - //assesses that future listener isn't triggered yet. - assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, and event is success - assertThat(future.isDone()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); + - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); } @Test - public void testAdvanced_redirect() { - // Sets up EventLoopGroup with 1 thread to be blocking. - EventLoopGroup group = new NioEventLoopGroup(1); - - // Sets up embedded channel. - setup("", makeBootstrap(group), false); - setupChannel(initialProtocol); - - // Initializes LocalAddress with unique String. - String host = TARGET_HOST + System.currentTimeMillis(); - LocalAddress address = new LocalAddress(host); + public void testSuccess_redirectHost() { + //setup + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); + setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); + HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); + //store future + ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); - // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group, address); - FullHttpResponse response = - new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + host, true, false)); + channel.writeInbound(originalResponse); - //checks that future has not been set to successful or a failure - assertThat(future.isDone()).isFalse(); + //gets changed protocol + Protocol newProtocol = initialProtocol.probingAction().protocol(); - channel.writeInbound(response); + //ensures that the new protocol has host and port specified by redirection + assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); + assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); + assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } + } From 2c1d0055eb1e881db057eacc4a79723b4c75abe1 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 257/337] Added missing license headers and JavaDoc --- .../handlers/ServerSideException.java | 16 ++++++- .../blackbox/messages/HttpRequestMessage.java | 45 ++++++++++++++----- .../messages/HttpResponseMessage.java | 32 ++++++++++--- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java index 5d3addb920e..441062a9e7b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; /** @@ -12,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 3fb8c187ad9..8fbb55c6339 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,13 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} + * (but needs to implement {@link OutboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion + * from {@link FullHttpRequest} to its type

+ */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +35,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,15 +42,22 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - if (buf == null) { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //creates message based on content found in original request + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //stores headers from request in finalRequest + request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); + + return finalRequest; + + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..776e7de0824 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,11 +1,33 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} + * (but needs to implement {@link InboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion + * from {@link FullHttpResponse} to its type

+ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -17,22 +39,20 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } + /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); + //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + //stores headers from response in finalResponse + response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); return finalResponse; } - - - } From 8d894f935ecf37077b84434fc76a13ea001391ba Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 258/337] Minor fix in NewChannelAction JavaDoc --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..1e7578d5679 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; - import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -28,8 +27,7 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) */ @AutoValue public abstract class NewChannelAction extends ProbingAction { From 984d0eab16794b1d132a880f743f7f2c5dbb3203 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 13:33:23 -0400 Subject: [PATCH 259/337] Minor Style Fix --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 ---- .../java/google/registry/monitoring/blackbox/Protocol.java | 1 - .../registry/monitoring/blackbox/handlers/ActionHandler.java | 1 - .../monitoring/blackbox/handlers/WebWhoisActionHandler.java | 2 -- 4 files changed, 8 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..84cf75492f2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -52,7 +52,6 @@ public Channel channel() { return this.channel; } - @Override public abstract Builder toBuilder(); @@ -120,7 +119,6 @@ public static NewChannelAction.Builder builder() return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -129,6 +127,4 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 05af501ad5a..22f3d27c08b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -109,4 +109,3 @@ public static abstract class Builder { public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 3fa60cd844a..503d211b324 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -80,4 +80,3 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 21010f0e887..5b77461cd8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -131,7 +131,5 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } } - - } From bf465f2aaa1852bdcc937e30abdfeaeda7bdb74b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 260/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 10 +- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 17 +- .../registry/monitoring/blackbox/Prober.java | 22 +- .../monitoring/blackbox/ProberModule.java | 83 ++++-- .../monitoring/blackbox/ProbingAction.java | 17 +- .../monitoring/blackbox/ProbingSequence.java | 117 +++++---- .../monitoring/blackbox/ProbingStep.java | 177 ++++++------- .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 12 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 ++++ .../monitoring/blackbox/WebWhoisModule.java | 168 ++++++------ .../exceptions/InternalException.java | 29 ++ .../exceptions/ResponseException.java | 29 ++ .../ServerSideException.java | 4 +- .../blackbox/handlers/ActionHandler.java | 88 ++++--- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/WebWhoisActionHandler.java | 19 +- .../handlers/WebWhoisMessageHandler.java | 31 +-- .../blackbox/messages/HttpRequestMessage.java | 50 +--- .../messages/HttpResponseMessage.java | 32 +-- .../blackbox/messages/InboundMessageType.java | 8 +- .../messages/OutboundMessageType.java | 11 +- .../blackbox/ProbingActionTest.java | 158 +++++------ .../blackbox/ProbingSequenceStepTest.java | 219 ++++++++++++++++ .../blackbox/TestServers/TestServer.java | 41 +++ .../blackbox/TestServers/WebWhoisServer.java | 15 +- .../monitoring/blackbox/TestUtils.java | 144 +++++++++- .../monitoring/blackbox/TokenTest.java | 60 +++++ .../blackbox/handlers/ConversionHandler.java | 11 +- .../blackbox/handlers/NettyRule.java | 62 +---- .../handlers/SslClientInitializerTest.java | 49 +++- .../blackbox/handlers/TestActionHandler.java | 15 +- .../handlers/WebWhoisActionHandlerTest.java | 247 +++++++++++++----- 36 files changed, 1534 insertions(+), 649 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/build.gradle b/prober/build.gradle index ae4bd27b731..b23314728e1 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -17,9 +17,10 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - + compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] compile deps['com.google.code.gson:gson'] @@ -40,11 +41,12 @@ dependencies { runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - + testCompile deps['com.google.truth:truth'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') + //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -54,3 +56,7 @@ dependencies { testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } +task(runMain, dependsOn: 'classes', type: JavaExec) { + main = 'google.registry.monitoring.blackbox.Prober' + classpath = sourceSets.main.runtimeClasspath +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 84cf75492f2..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -52,6 +53,7 @@ public Channel channel() { return this.channel; } + @Override public abstract Builder toBuilder(); @@ -83,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -116,9 +118,10 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } + @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -127,4 +130,6 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } + } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 36377247fa5..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,17 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index f9db4865f78..73bd9127852 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,68 +14,99 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import io.netty.channel.Channel; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.OpenSsl; -import io.netty.handler.ssl.SslProvider; import java.util.Set; import javax.inject.Singleton; -import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores - * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. + * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} + * + *

Provides

*/ @Module public class ProberModule { + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; - /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - - /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ @Provides - @Singleton - Class provideChannelClazz() { - return NioSocketChannel.class; + @HttpWhoisProtocol + ProbingSequence provideHttpWhoisSequence( + @HttpWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ + @Provides - @Singleton - Duration provideDuration() { - return DEFAULT_DURATION; + @HttpsWhoisProtocol + ProbingSequence provideHttpsWhoisSequence( + @HttpsWhoisProtocol ProbingStep probingStep, + EventLoopGroup eventLoopGroup) { + return new ProbingSequence.Builder() + .setClass(NioSocketChannel.class) + .addStep(probingStep) + .makeFirstRepeated() + .eventLoopGroup(eventLoopGroup) + .build(); } - /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; + } + + @Provides + @HttpsWhoisProtocol + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } - /** Root level {@link Component} that provides each {@link ProbingSequence}. */ + @Provides + ImmutableMap providePortToProtocolMap( + Set protocolSet) { + return Maps.uniqueIndex(protocolSet, Protocol::port); + } + + + @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, + TokenModule.class }) public interface ProberComponent { - //Standard WebWhois sequence - Set sequences(); + @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); + + @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); + + ImmutableMap providePortToProtocolMap(); + + @WebWhoisProtocol Token provideWebWhoisToken(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2441debb12d..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -34,7 +34,7 @@ import javax.inject.Provider; /** - *Superclass that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -183,4 +183,19 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + @Override + public String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n" + + "path: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host(), + path() + ); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 91c4165c068..6387207fea4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,86 +14,109 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. + * Represents Sequence of {@link ProbingSteps} that the Prober performs in order * + * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} + * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /**Each {@link ProbingSequence} requires a start token to begin running. */ - private Token startToken; + /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ + private EventLoopGroup eventGroup; - public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ + private Bootstrap bootstrap; + + public Bootstrap getBootstrap() { + return bootstrap; + } + + public void start(Token token) { + // calls the first step with input token; + firstStep.accept(token); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * {@link Builder} which takes in {@link ProbingStep}s + * + * @param Same specified {@code C} for overall {@link ProbingSequence} */ - public static class Builder { - - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - - private Token startToken; - - public Builder(Token startToken) { - this.startToken = startToken; + public static class Builder { + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstSequenceStep; + private EventLoopGroup eventLoopGroup; + private Class classType; + + Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; + return this; } - /** - * Adds {@link ProbingStep}, which is supplied with {@link Bootstrap}, - * built, and pointed to by the previous {@link ProbingStep} added. - */ - public Builder addStep(ProbingStep step) { - - if (currentStep == null) + Builder addStep(ProbingStep step) { + if (currentStep == null) { firstStep = step; - else + } else { currentStep.nextStep(step); - + } currentStep = step; return this; } - /** We take special note of the first repeated step. */ - public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; + /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ + Builder makeFirstRepeated() { + firstSequenceStep = currentStep; + return this; + } + /** Set the class to be the same as {@code C} */ + public Builder setClass(Class classType) { + this.classType = classType; return this; } - /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and - * calls private constructor to create {@link ProbingSequence}. - */ - public ProbingSequence build() { - if (firstRepeatedStep == null) - firstRepeatedStep = firstStep; - - currentStep.nextStep(firstRepeatedStep); + public ProbingSequence build() { + currentStep.nextStep(firstSequenceStep); currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); } + } - private ProbingSequence(ProbingStep firstStep, Token startToken) { + /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ + private void setParents() { + ProbingStep currentStep = firstStep.parent(this).nextStep(); + + while (currentStep != firstStep) { + currentStep = currentStep.parent(this).nextStep(); + } + } + private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, + Class classType) { this.firstStep = firstStep; - this.startToken = startToken; + this.eventGroup = eventLoopGroup; + this.bootstrap = new Bootstrap() + .group(eventGroup) + .channel(classType); + setParents(); + } + + @Override + public String toString() { + return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 3df536a9478..5bad5abf6bf 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,164 +14,155 @@ package google.registry.monitoring.blackbox; -import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.EppClientException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.io.IOException; import java.util.function.Consumer; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step - * in {@link ProbingSequence}. + * Represents generator of actions performed at each step in {@link ProbingSequence} + * + * @param See {@code C} in {@link ProbingSequence} * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. - * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, - * generates a new {@link ProbingAction} to call.

+ * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies + * these components on each loop iteration with the consumed {@link Token} and from that, + * generates new {@link ProbingAction} to perform<./p> * + *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -@AutoValue -public abstract class ProbingStep implements Consumer { +public abstract class ProbingStep implements Consumer { + public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); + protected static final Duration DEFAULT_DURATION = new Duration(2000L); private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Necessary boolean to inform when to obtain next {@link Token}*/ - protected boolean isLastStep = false; - private ProbingStep nextStep; - - /** Time delay duration between actions. */ - abstract Duration duration(); - - /** {@link Protocol} type for this step. */ - abstract Protocol protocol(); - - /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ - abstract OutboundMessageType messageTemplate(); - - /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ - abstract Bootstrap bootstrap(); - + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + protected LocalAddress address = DEFAULT_ADDRESS; - @AutoValue.Builder - public static abstract class Builder { - public abstract Builder setDuration(Duration value); + /** Necessary boolean to inform when to obtain next {@link Token}*/ + private boolean isLastStep = false; + private ProbingStep nextStep; + private ProbingSequence parent; - public abstract Builder setProtocol(Protocol value); + protected Duration duration; - public abstract Builder setMessageTemplate(OutboundMessageType value); + protected final Protocol protocol; + protected final OutboundMessageType message; - public abstract Builder setBootstrap(Bootstrap value); + protected ProbingStep(Protocol protocol, OutboundMessageType message) { + this.protocol = protocol; + this.message = message; + } - public abstract ProbingStep build(); + private OutboundMessageType message() { + return message; } - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); + Protocol protocol() { + return protocol; } + void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { - OutboundMessageType message = token.modifyMessage(messageTemplate()); - ProbingAction.Builder probingActionBuilder = ProbingAction.builder() - .setDelay(duration()) - .setProtocol(protocol()) - .setOutboundMessage(message) - .setHost(token.host()); - - if (token.channel() != null) - probingActionBuilder.setChannel(token.channel()); - else - probingActionBuilder.setBootstrap(bootstrap()); - - return probingActionBuilder.build(); + ProbingStep parent(ProbingSequence parent) { + this.parent = parent; + return this; } + /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + private ProbingAction generateAction(Token token) throws InternalException { + ProbingAction generatedAction; + + OutboundMessageType message = token.modifyMessage(message()); + + //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction + if (protocol().persistentConnection() && token.channel() != null) { + generatedAction = ExistingChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .channel(token.channel()) + .build(); + } else { + generatedAction = NewChannelAction.builder() + .delay(duration) + .protocol(protocol()) + .outboundMessage(message) + .host(token.getHost()) + .bootstrap(parent.getBootstrap()) + .address(address) + .build(); + + } + return generatedAction; + } - /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ + + /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

- */ @Override public void accept(Token token) { - ProbingAction currentAction; + ProbingAction nextAction; //attempt to generate new action. On error, move on to next step try { - currentAction = generateAction(token); - } catch(UndeterminedStateException e) { + nextAction = generateAction(token); + } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch(Exception e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; + //If the next step maintains the connection, pass on the channel from this + if (protocol().persistentConnection()) { + token.channel(nextAction.channel()); } + //call the created action + ChannelFuture future = nextAction.call(); + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - + nextStep.accept(generateNextToken(token)); } else { - //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - - if (protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n", + "OutboundMessage: %s\n" + + "and parent sequence: %s", protocol(), - messageTemplate().getClass().getName()); + message(), + parent); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 22f3d27c08b..06ce0532da0 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -108,4 +108,16 @@ public static abstract class Builder { public abstract Protocol build(); } + + @Override + public String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 1af4145bb10..dba905c0e49 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,96 +18,90 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; + +import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; - private static final String HTTP_PROTOCOL_NAME = "http"; - private static final String HTTPS_PROTOCOL_NAME = "https"; - - /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ - private static final int maximumMessageLengthBytes = 512 * 1024; + final static String DOMAIN_SUFFIX = "whois.nic."; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpWhoisProtocol {} + @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - public @interface HttpsWhoisProtocol {} + @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - /** {@link Provides} standard WebWhois sequence. */ + + + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + + @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { + @HttpWhoisProtocol + static ProbingStep provideHttpWhoisProbingSequence( + @HttpWhoisProtocol Protocol httpWhoisProtocol) { + return new ProbingStepWeb<>(httpWhoisProtocol); + } - return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) - .build(); + @Provides + @HttpsWhoisProtocol + static ProbingStep provideHttpsWhoisProbingStep( + @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { + return new ProbingStepWeb<>(httpsWhoisProtocol); } - /** {@link Provides} only step used in WebWhois sequence. */ + @Singleton @Provides - @WebWhoisProtocol - static ProbingStep provideWebWhoisStep( - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @WebWhoisProtocol Bootstrap bootstrap, - HttpRequestMessage messageTemplate, - Duration duration) { - - return ProbingStep.builder() - .setProtocol(httpWhoisProtocol) - .setBootstrap(bootstrap) - .setMessageTemplate(messageTemplate) - .setDuration(duration) + @HttpWhoisProtocol + static Protocol provideHttpWhoisProtocol( + @HttpWhoisProtocol int httpWhoisPort, + @HttpWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides - @HttpWhoisProtocol - static Protocol provideHttpWhoisProtocol( + @IntoSet + static Protocol provideHttpProtocolForSet( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTP_PROTOCOL_NAME) - .setPort(httpWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTP_PROTOCOL_NAME) + .port(httpWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ + @Singleton @Provides @HttpsWhoisProtocol @@ -115,21 +109,40 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .setName(HTTPS_PROTOCOL_NAME) - .setPort(httpsWhoisPort) - .setHandlerProviders(handlerProviders) - .setPersistentConnection(false) + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) .build(); } + @Singleton + @Provides + @IntoSet + static Protocol provideHttpsProtocolForSet( + @HttpsWhoisProtocol int httpsWhoisPort, + @HttpsWhoisProtocol ImmutableList> handlerProviders) { + return Protocol.builder() + .name(HTTPS_PROTOCOL_NAME) + .port(httpsWhoisPort) + .handlerProviders(handlerProviders) + .persistentConnection(false) + .build(); + } + + @Provides + @WebWhoisProtocol + String provideHttpWhoisHost() { + return "app"; + } + - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -138,14 +151,13 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - Provider messageHandlerProvider, + @WebWhoisProtocol Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -155,59 +167,33 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } - @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); - } - - @Provides - static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { - return new HttpObjectAggregator(maxContentLength); - } - - /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ - @Provides - @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); - } - /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ - @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap( - EventLoopGroup eventLoopGroup, - Class channelClazz){ - return new Bootstrap() - .group(eventLoopGroup) - .channel(channelClazz); + static MessageHandler provideMessageHandler() { + return new WebWhoisMessageHandler(); } @Provides - @WebWhoisProtocol - int provideMaximumMessageLengthBytes() { - return maximumMessageLengthBytes; + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); } - /** {@link Provides} the list of top level domains to be probed */ - @Singleton @Provides - @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); + static HttpObjectAggregator provideHttpObjectAggregator() { + return new HttpObjectAggregator(1048576); } @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return HTTP_WHOIS_PORT; + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } @Provides @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return HTTPS_WHOIS_PORT; + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 503d211b324..7898203e92d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -15,68 +15,88 @@ package google.registry.monitoring.blackbox.handlers; import com.google.common.flogger.FluentLogger; -import com.google.common.flogger.StackSize; -import io.netty.channel.ChannelInboundHandlerAdapter; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpResponse; -import java.util.function.Function; -import javax.inject.Inject; /** + *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline * - * @param Generic Type of Inbound Message - * @param Generic Type of Outbound Message - * Abstract class that tells sends message down pipeline and - * and tells listeners to move on when the message is received. + *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

+ * + *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} + * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception + * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses + * specify further work to be done for specific kinds of channel pipelines.

*/ -public abstract class ActionHandler extends SimpleChannelInboundHandler - implements Function { +public abstract class ActionHandler extends SimpleChannelInboundHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - protected ChannelPromise finished; - private Channel channel; + /** Three types of responses received down pipeline */ + public enum ResponseType {SUCCESS, FAILURE, ERROR} + /** Status of response for current {@link ActionHandler} instance */ + private static ResponseType status; - /** returns ChannelPromise for when inbound message is recieved - * a - * @param outboundMessage - * @return - */ - @Override - public ChannelFuture apply(O outboundMessage) { - // Sends request along Outbound Handlers on the Pipeline + protected ChannelPromise finished; - channel.writeAndFlush(outboundMessage); + /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + public ChannelFuture getFuture() { return finished; - - } - - public void resetFuture() { - finished = channel.newPromise(); } + /** Initializes new {@link ChannelPromise} */ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler - - channel = ctx.channel(); finished = ctx.newPromise(); } @Override - public void channelRead0(ChannelHandlerContext ctx, I inboundMessage) throws Exception{ - //Only purpose of Handler is to mark future as a success - + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + //simply marks finished as success + status = ResponseType.SUCCESS; finished.setSuccess(); } + /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.atSevere().withCause(cause).withStackTrace(StackSize.FULL).log("Exception Caught"); + logger.atSevere().withCause(cause).log(String.format( + "Attempted Action was unsuccessful with channel: %s, having pipeline: %s", + ctx.channel().toString(), + ctx.channel().pipeline().toString())); + + + if (ResponseException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + status = ResponseType.FAILURE; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (ServerSideException.class.isInstance(cause)) { + //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + status = ResponseType.ERROR; + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + } else if (InternalException.class.isInstance(cause)){ + logger.atSevere().withCause(cause).log("Severe internal error"); + finished.setFailure(cause); + } else { + finished.setFailure(cause); + } + + //due to failure, close channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 5b77461cd8f..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -17,20 +17,16 @@ import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; @@ -59,7 +55,7 @@ public WebWhoisActionHandler() {} */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ServerSideException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -67,9 +63,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - finished.setSuccess(); - logger.atInfo().log("Response Received: " + response); + super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -79,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -126,10 +121,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + throw new ResponseException("Response received from remote site was: " + response.status()); } } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 58c395ad86e..4afc5d95ba7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,52 +1,33 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; -/** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} - * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection. - */ -public class WebWhoisMessageHandler extends ChannelDuplexHandler { +public class WebWhoisMessageHandler extends MessageHandler { + + private HttpRequestMessage request; @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - HttpRequestMessage request = (HttpRequestMessage) msg; + request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + FullHttpResponse originalResponse = (FullHttpResponse) msg; - HttpResponseMessage response = new HttpResponseMessage(originalResponse); + InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8fbb55c6339..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,13 +6,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} - * (but needs to implement {@link OutboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion - * from {@link FullHttpRequest} to its type

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -35,6 +14,11 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + + @Override public HttpRequestMessage setUri(String path) { @@ -42,22 +26,16 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - - //creates message based on content found in original request - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - - - //stores headers from request in finalRequest - request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - - return finalRequest; - + HttpRequestMessage output; + if (buf == null) { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + } else { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + } + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 776e7de0824..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,33 +1,11 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} - * (but needs to implement {@link InboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion - * from {@link FullHttpResponse} to its type

- */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -39,20 +17,22 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } - /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); - //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - //stores headers from response in finalResponse - response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); return finalResponse; } + + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index cb9c96f37f6..0c1260becf2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -12,4 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.messages; + +/** + * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline + */ +public interface InboundMessageType {} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 6e3da3f69d2..0dd17e9d4a9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,17 +14,8 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; - /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType { - - /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; +public interface OutboundMessageType {} - /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - @Override - String toString(); -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index f7857dd80f9..cbcf2fc82b0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,19 +15,20 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -38,7 +39,6 @@ import io.netty.channel.nio.NioEventLoopGroup; import javax.inject.Provider; import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,65 +51,99 @@ * */ @RunWith(JUnit4.class) public class ProbingActionTest { - private static final String TEST_MESSAGE = "MESSAGE_TEST"; - private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private static final String ADDRESS_NAME = "TEST_ADDRESS"; - private static final int TEST_PORT = 0; - - private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + /** Necessary Constants for test */ + private final String TEST_MESSAGE = "MESSAGE_TEST"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final int TEST_PORT = 0; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = () -> testHandler; - private Provider conversionHandlerProvider = () -> conversionHandler; + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + private ProbingAction newChannelAction; + private ProbingAction existingChannelAction; + private EmbeddedChannel channel; + private Protocol protocol; /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); + /** Sets up a {@link Protocol} corresponding to when a new connection is created */ + private void setupNewChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(false) + .build(); + } + /** Sets up a {@link Protocol} corresponding to when a new connection exists */ + private void setupExistingChannelProtocol() { + protocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(TEST_PORT) + .persistentConnection(true) + .build(); + } + + /** Sets up a {@link NewChannelAction} with test specified attributes */ + private void setupNewChannelAction() { + newChannelAction = NewChannelAction.builder() + .bootstrap(bootstrap) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .address(address) + .build(); + } + + private void setupChannel() { + channel = new EmbeddedChannel(); + } + + /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + private void setupExistingChannelAction(Channel channel) { + existingChannelAction = ExistingChannelAction.builder() + .channel(channel) + .protocol(protocol) + .delay(Duration.ZERO) + .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .host("") + .build(); + } - @Ignore @Test public void testBehavior_existingChannel() { //setup - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up a Protocol corresponding to when a connection exists. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(true) - .build(); + setupChannel(); + setupExistingChannelProtocol(); + setupExistingChannelAction(channel); + channel.pipeline().addLast(conversionHandler); + channel.pipeline().addLast(testHandler); - // Sets up a ProbingAction that creates a channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setChannel(channel) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost("") - .build(); - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = existingChannelAction.call(); - //Obtains the outboundMessage passed through pipeline after delay - Object msg = null; - while (msg == null) { - msg = channel.readOutbound(); - } - //tests the passed message is exactly what we expect + //Ensures that we pass in the right message to the channel and haven't marked the future as success yet + Object msg = channel.readOutbound(); assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - assertThat(request).isEqualTo(TEST_MESSAGE); - - // Ensures that we haven't marked future as done until response is received. - assertThat(future.isDone()).isFalse(); + String response = ((ByteBuf) msg).toString(UTF_8); + assertThat(response).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()).isFalse(); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); @@ -121,41 +155,19 @@ public void testBehavior_existingChannel() { @Test public void testSuccess_newChannel() throws Exception { //setup - - LocalAddress address = new LocalAddress(ADDRESS_NAME); - Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); - - // Sets up a Protocol corresponding to when a new connection is created. - Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - + setupNewChannelProtocol(); + setupNewChannelAction(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - // Sets up a ProbingAction with existing channel using test specified attributes. - ProbingAction action = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new TestMessage(TEST_MESSAGE)) - .setHost(ADDRESS_NAME) - .build(); - - //tests main function of ProbingAction - ChannelFuture future = action.call(); + ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.syncUninterruptibly(); + future.sync(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(future.isSuccess()); + assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java new file mode 100644 index 00000000000..7a713017072 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java @@ -0,0 +1,219 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.TestUtils.TestStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.handlers.ConversionHandler; +import google.registry.monitoring.blackbox.handlers.NettyRule; +import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.junit.Rule; +import org.junit.Test; + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + + /** Used for testing how well probing step can create connection to blackbox server */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + + + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ + private ProbingSequence testSequence; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); + dummyStep = new DummyStep(testProtocol, eventLoopGroup); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(false) + .build(); + } + + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(true) + .build(); + } + + /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ + private void setupSequence() { + testSequence = new ProbingSequence.Builder() + .eventLoopGroup(eventLoopGroup) + .setClass(LocalChannel.class) + .addStep(firstStep) + .makeFirstRepeated() + .addStep(dummyStep) + .build(); + } + + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //there should be no next step + assertThat(firstStep.nextStep()).isNull(); + + //we expect that this exception be thrown + assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); + + } + + @Test + public void testWithSequence_NewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupSequence(); + setupNewChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupSequence(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 1da762b2c33..67e2cb7165d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,26 +1,37 @@ package google.registry.monitoring.blackbox.TestServers; +import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; /** * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform */ public abstract class TestServer { + private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + this.localAddress = localAddress; + //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override @@ -40,5 +51,35 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** Saves any inbound error as the cause of the promise failure. */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index a90ed987359..ab9997b6c68 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -5,13 +5,11 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -61,14 +59,14 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { + static class RedirectHandler extends ChannelDuplexHandler { private String redirectInput; private String destinationInput; /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; @@ -77,14 +75,15 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { + public void channelRead(ChannelHandlerContext ctx, Object msg) { + HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 50c60d9fc52..8d1722c9625 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,24 +14,47 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { + static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -56,19 +79,102 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain"); + response.headers().set("content-type", "text/plain").set("content-length", "0"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } + return response; + } + + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); return response; } + /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ + public static class TestProvider implements Provider { + + private E obj; + + public TestProvider(E obj) { + this.obj = obj; + } + + @Override + public E get() { + return obj; + } + } + + /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ + public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { + + String message; + + public DuplexMessageTest() { + message = ""; + } + + public DuplexMessageTest(String msg) { + message = msg; + } + + @Override + public String toString() { + return message; + } + } + + /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ + public static class TestStep extends ProbingStep { + + public TestStep(Protocol protocol, String testMessage, LocalAddress address) { + super(protocol, new DuplexMessageTest(testMessage)); + this.address = address; + this.duration = Duration.ZERO; + } + } + + /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ + public static class DummyStep extends ProbingStep { + private DefaultPromise future; + + public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { + super(protocol, new DuplexMessageTest()); + future = new DefaultPromise(eventLoopGroup.next()) {}; + duration = Duration.ZERO; + } + + @Override + public void accept(Token token) { + future.setSuccess(token); + } + public DefaultPromise getFuture() { + return future; + } + } + /** Basic outline for {@link Token} instances to be used in tests */ - static abstract class TestToken extends Token { - protected String host; + private static abstract class TestToken extends Token { + private String host; protected TestToken(String host) { this.host = host; @@ -84,7 +190,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String host() { + public String getHost() { return host; } @@ -114,5 +220,33 @@ public Channel channel() { return channel; } } + + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java new file mode 100644 index 00000000000..ef5cba5b60d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -0,0 +1,60 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + */ +@RunWith(JUnit4.class) +public class TokenTest { + + private static String PREFIX = "whois.nic."; + private static String TEST_STARTER = "starter"; + private static String TEST_DOMAIN = "test"; + + public Token webToken = new WebWhoisToken(TEST_DOMAIN); + + @Test + public void testWebToken_MessageModificationSuccess() { + //creates Request message with header + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + message.headers().set("host", TEST_STARTER); + + //attempts to use Token's method for modifying the method based on its stored host + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { + throw new RuntimeException(e); + } + + + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index c9d337d6ad8..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,13 +17,10 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -31,8 +28,8 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 86b54d9a07d..b6b5e8fbe0c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; + +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -25,11 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingActionTest; -import google.registry.monitoring.blackbox.ProbingStepTest; -import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -41,6 +41,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -51,8 +52,8 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

+ *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -79,19 +80,16 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { + public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, - ImmutableList.builder().add(handlers).add(echoHandler).build()); + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); } /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - Protocol protocol, - String host, + ProbingAction probingAction, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -111,9 +109,7 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROTOCOL_KEY, protocol) - .attr(REMOTE_ADDRESS_KEY, host); - + .attr(PROBING_ACTION_KEY, probingAction); channel = b.connect(localAddress).syncUninterruptibly().channel(); } @@ -122,7 +118,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertReceivedMessage(String message) throws Exception { + public void assertThatCustomWorks(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -163,38 +159,6 @@ ThrowableSubject assertThatClientRootCause() { } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** - * Saves any inbound error as the cause of the promise failure. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 523fb228752..469c62a8f75 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,14 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.ExistingChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; @@ -41,6 +45,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; +import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -62,6 +67,8 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { + private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); + /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -86,12 +93,15 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private final static Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); + private static final Protocol PROTOCOL = + Protocol.builder() + .name("ssl") + .port(SSL_PORT) + .handlerProviders(ImmutableList.of()) + .persistentConnection(false) + .build(); + + private ProbingAction probingAction; private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -103,13 +113,23 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } + private void setupProbingAction(Channel channel) { + probingAction = ExistingChannelAction.builder() + .delay(Duration.ZERO) + .host(SSL_HOST) + .channel(channel) + .outboundMessage(DEFAULT_MESSAGE) + .protocol(PROTOCOL) + .build(); + } + @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - channel.attr(PROTOCOL_KEY).set(PROTOCOL); - channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); + setupProbingAction(channel); + channel.attr(PROBING_ACTION_KEY).set(probingAction); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -140,7 +160,8 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -168,7 +189,8 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -197,7 +219,8 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); + setupProbingAction(new EmbeddedChannel()); + nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 95b06e623d1..518bb9ba686 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,7 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -23,18 +22,18 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ - private InboundMessageType receivedMessage; + private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage; + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } - public InboundMessageType getResponse() { + @Override + public String toString() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 63bb2cf5b53..d8a672758da 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,32 +15,44 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.NewChannelAction; +import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; +import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Unit tests for {@link WebWhoisActionHandler}. - * Attempts to test how well WebWhoIsActionHandler works - * when responding to all possible types of responses - * */ +/** + * Unit tests for {@link WebWhoisActionHandler}. + * + *

Attempts to test how well {@link WebWhoisActionHandler} works + * when responding to all possible types of responses

+ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; @@ -50,89 +62,96 @@ public class WebWhoisActionHandlerTest { private static final String REDIRECT_HOST = "www.example.com"; private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; + private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); + private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - + private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; + private ProbingAction probingAction; + private Provider actionHandlerProvider; + private void generateLocalAddress() { + address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); + } /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port, String host) { + private Protocol createProtocol(String name, int port) { return Protocol.builder() .name(name) .port(port) - .handlerProviders(ImmutableList.of()) - .build() - .host(host); + .handlerProviders(ImmutableList.of(actionHandlerProvider)) + .persistentConnection(false) + .build(); } /** Initializes new WebWhoisActionHandler */ private void setupActionHandler() { actionHandler = new WebWhoisActionHandler(); + actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol) { - setupActionHandler(); + private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + setupProbingActionBasic( + protocol, + outboundMessage, + makeBootstrap(new NioEventLoopGroup(1))); channel = new EmbeddedChannel(actionHandler); - channel.attr(PROTOCOL_KEY).set(protocol); + channel.attr(PROBING_ACTION_KEY).set(probingAction); } + private Bootstrap makeBootstrap(EventLoopGroup group) { + return new Bootstrap() + .group(group) + .channel(LocalChannel.class); + } /**Sets up probingAction for when testing redirection */ - private void setupProbingAction(Protocol protocol, HttpRequest outboundMessage, Bootstrap bootstrap) { - NewChannelAction.builder() + private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { + probingAction = NewChannelAction.builder() .protocol(protocol) .outboundMessage(outboundMessage) .delay(DEFAULT_DURATION) .bootstrap(bootstrap) + .host(TARGET_HOST) + .address(DEFAULT_ADDRESS) .build(); } - /** Sets up everything specified in above methods*/ - private void setupChannelWithProbingAction(Protocol protocol, HttpRequest outboundMessage) { - setupProbingAction( - protocol, - outboundMessage, - new Bootstrap() - .group(new NioEventLoopGroup()) - .channel(NioSocketChannel.class)); - setupChannel(protocol); + private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + probingAction = NewChannelAction.builder() + .protocol(protocol) + .outboundMessage(outboundMessage) + .delay(DEFAULT_DURATION) + .bootstrap(bootstrap) + .host(host) + .address(address) + .build(); } - - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ - private static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { - FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); - if (location != null) { - response.headers().set("location", location); - } - if (keepAlive) { - response.headers().set("connection", "keep-alive"); - } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; + private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testSuccess_responseOk() { + public void testBasic_responseOk() throws Exception { //setup - Protocol initialProtocol = createProtocol("responseOk", 0, ""); - setupChannel(initialProtocol); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.OK); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -140,25 +159,30 @@ public void testSuccess_responseOk() { channel.writeInbound(response); - //assesses that we successfully receivved good response and protocol is unchanged + //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testSuccess_responseBad() { + public void testBasic_responseFailure() { //setup - Protocol initialProtocol = createProtocol("responseBad", 0, ""); - setupChannel(initialProtocol); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseBad", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest("", "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeHttpResponse(HttpResponseStatus.BAD_REQUEST); + FullHttpResponse response = HttpResponseMessage + .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -167,24 +191,63 @@ public void testSuccess_responseBad() { //assesses that listener is triggered, but event is not success assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isFalse(); + assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + } + @Test + public void testBasic_responseError() { + //setup + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseError", 0); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + + //stores future + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); + + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + + //assesses that future listener isn't triggered yet. + assertThat(testPromise.isSuccess()).isFalse(); + + channel.writeInbound(response); + + //assesses that listener is triggered, and event is success + assertThat(testPromise.isSuccess()).isTrue(); + assertThat(future.isSuccess()).isTrue(); + //ensures Protocol is the same + assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); } @Test - public void testSuccess_redirectCloseChannel() { + public void testBasic_redirectCloseChannel() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", 0, ""); - HttpRequest outboundMessage = makeHttpGetRequest("", ""); - setupChannelWithProbingAction(initialProtocol, outboundMessage); + HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", 0); + generateLocalAddress(); + setupChannel(initialProtocol, outboundMessage); //stores future - ChannelFuture future = actionHandler.apply(outboundMessage); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(outboundMessage); + + //setup for checker to ensure future listener isn't triggered to early + ChannelPromise testPromise = channel.newPromise(); + future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false); + FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + //checks that future has not been set to successful or a failure + assertThat(testPromise.isSuccess()).isFalse(); channel.writeInbound(response); @@ -195,27 +258,69 @@ public void testSuccess_redirectCloseChannel() { } @Test - public void testSuccess_redirectHost() { + public void testBasic_redirectHost() { //setup - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, ""); - setupChannelWithProbingAction(initialProtocol, makeHttpGetRequest(TARGET_HOST, "")); - HttpResponse originalResponse = makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + generateLocalAddress(); + setupChannel(initialProtocol, msg); + HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + //store future - ChannelFuture future = actionHandler.apply(makeHttpGetRequest(TARGET_HOST, "")); + ChannelFuture future = actionHandler.getFuture(); + channel.writeOutbound(msg); channel.writeInbound(originalResponse); + ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + //gets changed protocol - Protocol newProtocol = initialProtocol.probingAction().protocol(); + Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.host()).isEqualTo(REDIRECT_HOST); assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newProtocol.path()).isEqualTo(REDIRECT_PATH); + assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); + assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); + } + + @Test + public void testAdvanced_responseOk() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); + setupLocalServer("", TARGET_HOST, group); + //stores future + ChannelFuture future = probingAction.call(); + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); + } + + @Test + public void testAdvanced_responseFailure() { + //setup + EventLoopGroup group = new NioEventLoopGroup(1); + HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(); + Protocol initialProtocol = createProtocol("responseOk", 0); + generateLocalAddress(); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + setupLocalServer("", TARGET_HOST, group); + + //stores future + ChannelFuture future = probingAction.call(); + + //assesses that we successfully received good response and protocol is unchanged + assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } } + From d95faac41580b9c994e1eb0f94e91fd70d94de2c Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 261/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 +++++++++----- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/ProbingSequence.java | 1 - .../monitoring/blackbox/ProbingStep.java | 7 +--- .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 - .../monitoring/blackbox/Tokens/Token.java | 4 +- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../monitoring/blackbox/WebWhoisModule.java | 2 +- .../exceptions/EppClientException.java | 29 ------------- .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++- .../handlers/WebWhoisMessageHandler.java | 22 +++++++++- .../blackbox/messages/HttpRequestMessage.java | 41 +++++++++++++------ .../messages/HttpResponseMessage.java | 26 ++++++++---- .../blackbox/messages/InboundMessageType.java | 1 - .../messages/OutboundMessageType.java | 1 - .../blackbox/TestServers/TestServer.java | 16 +++++++- .../blackbox/TestServers/WebWhoisServer.java | 18 +++++++- 20 files changed, 145 insertions(+), 86 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6387207fea4..2eb90a1d6c3 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -119,4 +119,3 @@ public String toString() { } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 5bad5abf6bf..80b04a3d0c9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.exceptions.EppClientException; import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; import io.netty.channel.local.LocalAddress; -import java.io.IOException; + import java.util.function.Consumer; import org.joda.time.Duration; @@ -164,7 +162,4 @@ public String toString() { message(), parent); } - } - - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 06ce0532da0..8e307b07296 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -120,4 +120,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dba905c0e49..7200a1877e2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -197,4 +197,4 @@ static SslClientInitializer provideSslClientInitializer(SslPro } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 4afc5d95ba7..0acf223eb9e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; @@ -8,6 +22,11 @@ import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; +/** + * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} + * in case of reuse for redirection + */ public class WebWhoisMessageHandler extends MessageHandler { private HttpRequestMessage request; @@ -15,6 +34,7 @@ public class WebWhoisMessageHandler extends MessageHandler { @Inject public WebWhoisMessageHandler() {} + /** Retains {@link HttpRequestMessage} and calls super write method*/ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { request = (HttpRequestMessage) msg; @@ -23,9 +43,9 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) } + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - FullHttpResponse originalResponse = (FullHttpResponse) msg; InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); super.channelRead(ctx, response); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..b06938d80a1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +31,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,16 +38,19 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + + request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + + return finalRequest; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..283b14440ac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,7 +33,7 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); @@ -26,13 +43,8 @@ public static HttpResponseMessage fromResponse(FullHttpResponse response) { else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); return finalResponse; } - - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 0c1260becf2..578526933ba 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ public interface InboundMessageType {} - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 0dd17e9d4a9..2d5df10f8c1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -18,4 +18,3 @@ * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType {} - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 67e2cb7165d..a4474b6b8b5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static com.google.common.truth.Truth.assertThat; @@ -20,7 +34,7 @@ import java.util.concurrent.Future; /** - * Mock Server Superclass whose subclasses implement specific behaviours we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { private LocalAddress localAddress; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index ab9997b6c68..06b19ea3607 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.TestServers; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; @@ -20,10 +34,10 @@ /** * {@link TestServer} subtype that performs WebWhois Services Expected * - * It will either redirect the client to the correct location if given the + *

It will either redirect the client to the correct location if given the * requisite redirect input, give the client a successful response if they give * the expected final destination, or give the client an error message if given - * an unexpected host location + * an unexpected host location

*/ public class WebWhoisServer extends TestServer { From 17b826d88ef6e6fd3fde8507dd00cacef6888523 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 262/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 --- .../monitoring/blackbox/NewChannelAction.java | 144 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProberModule.java | 80 ++--- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingSequence.java | 130 ++++----- .../monitoring/blackbox/ProbingStep.java | 147 +++++----- .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/Protocol.java | 78 +---- .../monitoring/blackbox/TokenModule.java | 35 --- .../monitoring/blackbox/Tokens/Token.java | 47 --- .../blackbox/Tokens/WebWhoisToken.java | 54 ---- .../monitoring/blackbox/WebWhoisModule.java | 169 ++++++----- .../exceptions/ConnectionException.java | 5 +- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/ActionHandler.java | 102 +++++-- .../blackbox/handlers/MessageHandler.java | 24 -- .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../handlers/WebWhoisMessageHandler.java | 17 +- .../blackbox/messages/HttpRequestMessage.java | 46 ++- .../messages/HttpResponseMessage.java | 14 +- .../messages/OutboundMessageType.java | 11 +- .../monitoring/blackbox/tokens/Token.java | 20 +- .../blackbox/tokens/WebWhoisToken.java | 32 +- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 32 files changed, 704 insertions(+), 987 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 73bd9127852..0daaf16ded4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,99 +14,59 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.Set; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; import javax.inject.Singleton; +import org.joda.time.Duration; /** - * {@link Dagger} main module, which Provides {@link ProbingSequences} and houses {@link ProberComponent} - * - *

Provides

+ * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores + * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. */ @Module public class ProberModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; + /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + private static final Duration DEFAULT_DURATION = new Duration(4000L); + + /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides - @HttpWhoisProtocol - ProbingSequence provideHttpWhoisSequence( - @HttpWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpsWhoisProtocol - ProbingSequence provideHttpsWhoisSequence( - @HttpsWhoisProtocol ProbingStep probingStep, - EventLoopGroup eventLoopGroup) { - return new ProbingSequence.Builder() - .setClass(NioSocketChannel.class) - .addStep(probingStep) - .makeFirstRepeated() - .eventLoopGroup(eventLoopGroup) - .build(); - } - - @Provides - @HttpWhoisProtocol - int provideHttpWhoisPort() { - return httpWhoIsPort; - } - - @Provides - @HttpsWhoisProtocol - int provideHttpsWhoisPort() { - return httpsWhoIsPort; + @Singleton + Duration provideDuration() { + return DEFAULT_DURATION; } + /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides - ImmutableMap providePortToProtocolMap( - Set protocolSet) { - return Maps.uniqueIndex(protocolSet, Protocol::port); + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } - - + /** Root level {@link Component} that provides each {@link ProbingSequence}. */ @Singleton @Component( modules = { ProberModule.class, WebWhoisModule.class, - TokenModule.class }) public interface ProberComponent { - @HttpWhoisProtocol ProbingSequence provideHttpWhoisSequence(); - - @HttpsWhoisProtocol ProbingSequence provideHttpsWhoisSequence(); - - ImmutableMap providePortToProtocolMap(); - - @WebWhoisProtocol Token provideWebWhoisToken(); + //Standard WebWhois sequence + @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2eb90a1d6c3..2dbf48256f9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,108 +14,100 @@ package google.registry.monitoring.blackbox; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.EventLoopGroup; /** - * Represents Sequence of {@link ProbingSteps} that the Prober performs in order + * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - * @param Primarily for testing purposes to specify channel type. Usually is {@link NioSocketChannel} - * but for tests is {@link LocalChannel} * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep}s in order and mark which one is the first repeated step.

+ * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

* *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work

+ * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence { + private ProbingStep firstStep; - /** A given {@link Prober} will run each of its {@link ProbingSequence}s with the same given {@link EventLoopGroup} */ - private EventLoopGroup eventGroup; + /**Each {@link ProbingSequence} requires a start token to begin running. */ + private Token startToken; - /** Each {@link ProbingSequence} houses its own {@link Bootstrap} instance */ - private Bootstrap bootstrap; - - public Bootstrap getBootstrap() { - return bootstrap; - } - - public void start(Token token) { - // calls the first step with input token; - firstStep.accept(token); + public void start() { + // calls the first step with startToken; + firstStep.accept(startToken); } /** - * {@link Builder} which takes in {@link ProbingStep}s - * - * @param Same specified {@code C} for overall {@link ProbingSequence} + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. */ - public static class Builder { - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstSequenceStep; - private EventLoopGroup eventLoopGroup; - private Class classType; - - Builder eventLoopGroup(EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public static class Builder { + + private ProbingStep currentStep; + private ProbingStep firstStep; + private ProbingStep firstRepeatedStep; + private Bootstrap bootstrap; + private Token startToken; + + /** + * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. + * + *

Must be called before adding {@link ProbingStep.Builder}s.

+ */ + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } + + /** Adds start token that activate {@link ProbingSequence}. */ + public Builder addToken(Token token) { + startToken = token; return this; } - Builder addStep(ProbingStep step) { - if (currentStep == null) { + /** + * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, + * built, and pointed to by the previous {@link ProbingStep} added. + */ + public Builder addStep(ProbingStep.Builder stepBuilder) { + assert (bootstrap != null); + ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); + + if (currentStep == null) firstStep = step; - } else { + else currentStep.nextStep(step); - } + currentStep = step; return this; } - /** We take special note of the first repeated step and set pointers in {@link ProbingStep}s appropriately */ - Builder makeFirstRepeated() { - firstSequenceStep = currentStep; - return this; - } - /** Set the class to be the same as {@code C} */ - public Builder setClass(Class classType) { - this.classType = classType; + /** We take special note of the first repeated step. */ + public Builder markFirstRepeated() { + firstRepeatedStep = currentStep; return this; } - public ProbingSequence build() { - currentStep.nextStep(firstSequenceStep); + /** + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and + * calls private constructor to create {@link ProbingSequence}. + */ + public ProbingSequence build() { + if (firstRepeatedStep == null) + firstRepeatedStep = firstStep; + + currentStep.nextStep(firstRepeatedStep); currentStep.lastStep(); - return new ProbingSequence<>(this.firstStep, this.eventLoopGroup, this.classType); + return new ProbingSequence(this.firstStep, this.startToken); } - } - /** We point each {@link ProbingStep} to the parent {@link ProbingSequence} so it can access its {@link Bootstrap} */ - private void setParents() { - ProbingStep currentStep = firstStep.parent(this).nextStep(); - - while (currentStep != firstStep) { - currentStep = currentStep.parent(this).nextStep(); - } - } - private ProbingSequence(ProbingStep firstStep, EventLoopGroup eventLoopGroup, - Class classType) { + private ProbingSequence(ProbingStep firstStep, Token startToken) { this.firstStep = firstStep; - this.eventGroup = eventLoopGroup; - this.bootstrap = new Bootstrap() - .group(eventGroup) - .channel(classType); - setParents(); - } - - @Override - public String toString() { - return String.format("ProbingSequence with EventLoopGroup: %s and Bootstrap %s", eventGroup, bootstrap); - + this.startToken = startToken; } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 80b04a3d0c9..d54acef325a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -14,152 +14,145 @@ package google.registry.monitoring.blackbox; +import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.local.LocalAddress; - import java.util.function.Consumer; import org.joda.time.Duration; /** - * Represents generator of actions performed at each step in {@link ProbingSequence} - * - * @param See {@code C} in {@link ProbingSequence} + * {@link AutoValue} class that represents generator of actions performed at each step + * in {@link ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType} and {@link Protocol} instances. It then modifies - * these components on each loop iteration with the consumed {@link Token} and from that, - * generates new {@link ProbingAction} to perform<./p> + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. + * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, + * generates a new {@link ProbingAction} to call.

* - *

Subclasses specify {@link Protocol} and {@link OutboundMessageType} of the {@link ProbingStep}

*/ -public abstract class ProbingStep implements Consumer { +@AutoValue +public abstract class ProbingStep implements Consumer { - public static final LocalAddress DEFAULT_ADDRESS = new LocalAddress("DEFAULT_ADDRESS_CHECKER"); - protected static final Duration DEFAULT_DURATION = new Duration(2000L); - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - protected LocalAddress address = DEFAULT_ADDRESS; + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ private boolean isLastStep = false; - private ProbingStep nextStep; - private ProbingSequence parent; + private ProbingStep nextStep; - protected Duration duration; + abstract Duration duration(); + abstract Protocol protocol(); + abstract OutboundMessageType messageTemplate(); + abstract Bootstrap bootstrap(); - protected final Protocol protocol; - protected final OutboundMessageType message; - protected ProbingStep(Protocol protocol, OutboundMessageType message) { - this.protocol = protocol; - this.message = message; - } + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder setDuration(Duration value); - private OutboundMessageType message() { - return message; - } + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); - Protocol protocol() { - return protocol; + public abstract ProbingStep build(); } + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } void lastStep() { isLastStep = true; } - void nextStep(ProbingStep step) { + void nextStep(ProbingStep step) { this.nextStep = step; } - ProbingStep nextStep() { + ProbingStep nextStep() { return this.nextStep; } - ProbingStep parent(ProbingSequence parent) { - this.parent = parent; - return this; - } - - /** Generates a new {@link ProbingAction} from token modified message and {@link Protocol} */ + /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ private ProbingAction generateAction(Token token) throws InternalException { - ProbingAction generatedAction; - - OutboundMessageType message = token.modifyMessage(message()); - - //Depending on whether token passes a channel, we make a NewChannelAction or ExistingChannelAction - if (protocol().persistentConnection() && token.channel() != null) { - generatedAction = ExistingChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .channel(token.channel()) - .build(); - } else { - generatedAction = NewChannelAction.builder() - .delay(duration) - .protocol(protocol()) - .outboundMessage(message) - .host(token.getHost()) - .bootstrap(parent.getBootstrap()) - .address(address) - .build(); - - } - return generatedAction; + OutboundMessageType message = token.modifyMessage(messageTemplate()); + ProbingAction.Builder probingActionBuilder = ProbingAction.builder() + .setDelay(duration()) + .setProtocol(protocol()) + .setOutboundMessage(message) + .setHost(token.getHost()) + .setBootstrap(bootstrap()); + + if (token.channel() != null) + probingActionBuilder.setChannel(token.channel()); + + return probingActionBuilder.build(); } - /** On the last step, get the next {@link Token}. Otherwise, use the same one. */ + /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } @Override public void accept(Token token) { - ProbingAction nextAction; + ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - nextAction = generateAction(token); + currentAction = generateAction(token); } catch(InternalException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - //If the next step maintains the connection, pass on the channel from this - if (protocol().persistentConnection()) { - token.channel(nextAction.channel()); - } + //call the created action - ChannelFuture future = nextAction.call(); + ChannelFuture future; + + try { + future = currentAction.call(); + + } catch(InternalException e) { + logger.atWarning().withCause(e).log("Error in Action Performed"); + nextStep.accept(generateNextToken(token)); + return; + } + //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - nextStep.accept(generateNextToken(token)); + //If the next step maintains the connection, pass on the channel from this } else { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + token.setChannel(currentAction.channel()); + + nextStep.accept(generateNextToken(token)); + + }); } @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n" + - "and parent sequence: %s", + "OutboundMessage: %s\n", protocol(), - message(), - parent); + messageTemplate().getClass().getName()); } + } + + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 8e307b07296..88b4c7aa6f6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -16,95 +16,43 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import io.netty.util.AttributeKey; import io.netty.channel.ChannelHandler; +import io.netty.util.AttributeKey; import javax.inject.Provider; /** - * Protocol Class packages all static variables necessary for a certain type of connection - * Both the host and the path can be changed for the same protocol - * Mainly packages the handlers necessary for the requisite channel pipeline + * {@link AutoValue} class that stores all unchanged variables necessary for type of connection. */ @AutoValue public abstract class Protocol { - public final static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - - /** - * Default names associated with each protocol - */ - final static String EPP_PROTOCOL_NAME = "EPP"; - final static String DNS_PROTOCOL_NAME = "DNS"; - final static String WHOIS_PROTOCOL_NAME = "WHOIS"; - final static String RDAP_PROTOCOL_NAME = "RDAP"; - - private String host; - private String path = ""; - private ProbingAction probingAction; - - /** Setter method for Protocol's host*/ - public Protocol host(String host) { - this.host = host; - return this; - } + /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - /** Getter method for Protocol's host*/ - public String host() { - return host; - } - - /** Setter method for Protocol's path*/ - public Protocol path(String path) { - this.path = path; - return this; - } - - /** Getter method for Protocol's path*/ - public String path() { - return path; - } + abstract String name(); - /** Setter method for Protocol's ProbingAction parent*/ - public Protocol probingAction(ProbingAction probingAction) { - this.probingAction = probingAction; - return this; - } - - /** Getter method for Protocol's path*/ - public ProbingAction probingAction() { - return probingAction; - } - - /** If connection associated with Protocol is persistent, which is only EPP */ - public boolean persistentConnection() { - return name() == EPP_PROTOCOL_NAME; - } - - /** Protocol Name */ - public abstract String name(); - - /** Port to bind to at remote host */ public abstract int port(); /** The {@link ChannelHandler} providers to use for the protocol, in order. */ - public abstract ImmutableList> handlerProviders(); - + abstract ImmutableList> handlerProviders(); - public abstract Builder toBuilder(); + /** Boolean that notes if connection associated with Protocol is persistent.*/ + abstract boolean persistentConnection(); public static Builder builder() { return new AutoValue_Protocol.Builder(); } - @AutoValue.Builder public static abstract class Builder { - public abstract Builder name(String value); + public abstract Builder setName(String value); + + public abstract Builder setPort(int num); - public abstract Builder port(int num); + public abstract Builder setHandlerProviders(ImmutableList> providers); - public abstract Builder handlerProviders(ImmutableList> providers); + public abstract Builder setPersistentConnection(boolean value); public abstract Protocol build(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 7200a1877e2..dcc9635beaa 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,62 +17,86 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; -import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.handlers.MessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandler; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; +import org.joda.time.Duration; /** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ @Module public class WebWhoisModule { - final static String DOMAIN_SUFFIX = "whois.nic."; + private final int httpWhoIsPort = 80; + private final int httpsWhoIsPort = 443; + private static final String HTTP_PROTOCOL_NAME = "whois_http"; + private static final String HTTPS_PROTOCOL_NAME = "whois_https"; + private static final String DOMAIN_PREFIX = "whois.nic."; + + /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + private static final int maximumMessageLengthBytes = 512 * 1024; /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpWhoisProtocol {} + public @interface HttpWhoisProtocol {} /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ @Qualifier - @interface HttpsWhoisProtocol {} + public @interface HttpsWhoisProtocol {} /** Dagger qualifier to provide any WebWhois related bindings. */ @Qualifier public @interface WebWhoisProtocol {} - - - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - - + /** {@link Provides} standard WebWhois sequence. */ @Provides - @HttpWhoisProtocol - static ProbingStep provideHttpWhoisProbingSequence( - @HttpWhoisProtocol Protocol httpWhoisProtocol) { - return new ProbingStepWeb<>(httpWhoisProtocol); + @WebWhoisProtocol + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, + WebWhoisToken webWhoisToken, + @WebWhoisProtocol Bootstrap bootstrap) { + + return new ProbingSequence.Builder() + .addToken(webWhoisToken) + .setBootstrap(bootstrap) + .addStep(probingStepBuilder) + .build(); } + + /** {@link Provides} only step used in WebWhois sequence. */ @Provides - @HttpsWhoisProtocol - static ProbingStep provideHttpsWhoisProbingStep( - @HttpsWhoisProtocol Protocol httpsWhoisProtocol) { - return new ProbingStepWeb<>(httpsWhoisProtocol); + @WebWhoisProtocol + static ProbingStep.Builder provideWebWhoisStepBuilder( + @HttpWhoisProtocol Protocol httpWhoisProtocol, + HttpRequestMessage messageTemplate, + Duration duration) { + + return ProbingStep.builder() + .setProtocol(httpWhoisProtocol) + .setMessageTemplate(messageTemplate) + .setDuration(duration); } - + /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @Singleton @Provides @HttpWhoisProtocol @@ -80,28 +104,14 @@ static Protocol provideHttpWhoisProtocol( @HttpWhoisProtocol int httpWhoisPort, @HttpWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpProtocolForSet( - @HttpWhoisProtocol int httpWhoisPort, - @HttpWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTP_PROTOCOL_NAME) - .port(httpWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTP_PROTOCOL_NAME) + .setPort(httpWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } - + /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ @Singleton @Provides @HttpsWhoisProtocol @@ -109,40 +119,28 @@ static Protocol provideHttpsWhoisProtocol( @HttpsWhoisProtocol int httpsWhoisPort, @HttpsWhoisProtocol ImmutableList> handlerProviders) { return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) - .build(); - } - - @Singleton - @Provides - @IntoSet - static Protocol provideHttpsProtocolForSet( - @HttpsWhoisProtocol int httpsWhoisPort, - @HttpsWhoisProtocol ImmutableList> handlerProviders) { - return Protocol.builder() - .name(HTTPS_PROTOCOL_NAME) - .port(httpsWhoisPort) - .handlerProviders(handlerProviders) - .persistentConnection(false) + .setName(HTTPS_PROTOCOL_NAME) + .setPort(httpsWhoisPort) + .setHandlerProviders(handlerProviders) + .setPersistentConnection(false) .build(); } + /** {@link Provides} the prefix where we probe: "prefix.tld". */ @Provides - @WebWhoisProtocol - String provideHttpWhoisHost() { - return "app"; + @Named("Web-WHOIS-Prefix") + String provideWhoisPrefix() { + return DOMAIN_PREFIX; } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( httpClientCodecProvider, @@ -151,13 +149,14 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } + /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( @HttpsWhoisProtocol Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, - @WebWhoisProtocol Provider messageHandlerProvider, + Provider messageHandlerProvider, Provider webWhoisActionHandlerProvider) { return ImmutableList.of( sslClientInitializerProvider, @@ -167,33 +166,57 @@ static ImmutableList> providerHttpsWhoisHandl webWhoisActionHandlerProvider); } + @Provides + static HttpClientCodec provideHttpClientCodec() { + return new HttpClientCodec(); + } + + @Provides + static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) { + return new HttpObjectAggregator(maxContentLength); + } + + /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + @Provides + @HttpsWhoisProtocol + static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + return new SslClientInitializer<>(sslProvider); + } + /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + @Singleton @Provides @WebWhoisProtocol - static MessageHandler provideMessageHandler() { - return new WebWhoisMessageHandler(); + static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + return new Bootstrap() + .group(eventLoopGroup) + .channel(NioSocketChannel.class); } @Provides - static HttpClientCodec provideHttpClientCodec() { - return new HttpClientCodec(); + @WebWhoisProtocol + int provideMaximumMessageLengthBytes() { + return maximumMessageLengthBytes; } + /** {@link Provides} the list of top level domains to be probed */ + @Singleton @Provides - static HttpObjectAggregator provideHttpObjectAggregator() { - return new HttpObjectAggregator(1048576); + @WebWhoisProtocol + ImmutableList provideTopLevelDomains() { + return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); } @Provides - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + @HttpWhoisProtocol + int provideHttpWhoisPort() { + return httpWhoIsPort; } @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { - return new SslClientInitializer<>(sslProvider); + int provideHttpsWhoisPort() { + return httpsWhoIsPort; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index adb833ec629..be3d725c833 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,10 +15,9 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when - * the action performed failed due to an issue in the connection with the server. + * Base exception class for all instances when the status of the action performed is ERROR. */ -public class ConnectionException extends UndeterminedStateException { +public class ConnectionException extends Exception { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 7898203e92d..e397393b4e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,10 +14,11 @@ package google.registry.monitoring.blackbox.handlers; +import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; @@ -26,16 +27,18 @@ import io.netty.channel.ChannelPromise; /** - *Superclass of all {@link ChannelHandler}s placed at end of channel pipeline + *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in + * messages that implement the {@link InboundMessageType} interface.

* - *

The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType} - * passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception - * thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses - * specify further work to be done for specific kinds of channel pipelines.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, + * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed + * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} + * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * + *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ public abstract class ActionHandler extends SimpleChannelInboundHandler { @@ -47,28 +50,42 @@ public enum ResponseType {SUCCESS, FAILURE, ERROR} /** Status of response for current {@link ActionHandler} instance */ private static ResponseType status; + /** {@link ChannelPromise} that informs {@link google.registry.monitoring.blackbox.ProbingAction} if response has been received. */ protected ChannelPromise finished; - /** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/ + /** Returns initialized {@link ChannelPromise} to {@link google.registry.monitoring.blackbox.ProbingAction}.*/ public ChannelFuture getFuture() { return finished; } - /** Initializes new {@link ChannelPromise} */ + /** Initializes the same {@link ChannelPromise}*/ @Override public void handlerAdded(ChannelHandlerContext ctx) { //Once handler is added to channel pipeline, initialize channel and future for this handler finished = ctx.newPromise(); } + /** Initializes the same {@link ChannelPromise} in case current channel is reused (usually for EPP).*/ + public void resetFuture() { + finished = finished.channel().newPromise(); + } + + /** Marks {@link ResponseType} and {@link ChannelPromise} as success */ @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { - //simply marks finished as success + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { + status = ResponseType.SUCCESS; - finished.setSuccess(); + + if (!finished.isSuccess()) { + finished.setSuccess(); + } } - /** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */ + /** + * Logs the channel and pipeline that caused error, closes channel, then informs + * {@link google.registry.monitoring.blackbox.ProbingAction} listeners of error. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.atSevere().withCause(cause).log(String.format( @@ -76,27 +93,62 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.channel().toString(), ctx.channel().pipeline().toString())); - - if (ResponseException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was a FAILURE + if (cause instanceof ResponseException) { + //On ResponseException, we know the response is a failure. As a result, + //we set the status to FAILURE, then inform the MetricsHandler of this status = ResponseType.FAILURE; + + //Since it wasn't a success, we still want to log to see what caused the FAILURE logger.atInfo().log(cause.getMessage()); + + //As always, inform the ProbingStep that we successfully completed this action finished.setSuccess(); - } else if (ServerSideException.class.isInstance(cause)) { - //TODO - add in metrics handling to inform MetricsCollector the status of the task was an ERROR + + } else if (cause instanceof ConnectionException) { + //On ConnectionException, we know the response type is an error. As a result, + //we set the status to ERROR, then inform the MetricsHandler of this status = ResponseType.ERROR; + + //Since it wasn't a success, we still log what caused the ERROR logger.atInfo().log(cause.getMessage()); finished.setSuccess(); - } else if (InternalException.class.isInstance(cause)){ + + //As this was an ERROR in the connection, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + } else if (cause instanceof InternalException){ + //For an internal error, metrics should not be collected, so we log what caused this, and + //inform the ProbingStep the Prober had an internal error on this action logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); + + + //As this was an internal error, we must close the channel + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + } else { - finished.setFailure(cause); + //In the case of any other kind of error, we assume it is some type of connection ERROR, + //so we treat it as such: + + status = ResponseType.ERROR; + + logger.atInfo().log(cause.getMessage()); + finished.setSuccess(); + + ChannelFuture closedFuture = ctx.channel().close(); + closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - //due to failure, close channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); + + + } + + /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ + @VisibleForTesting + ResponseType getStatus() { + return status; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index ac844ac99df..919006592ea 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -89,8 +90,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); - Protocol protocol = action.protocol(); + Protocol protocol = channel.attr(PROTOCOL_KEY).get(); + String host = channel.attr(REMOTE_ADDRESS_KEY).get(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -103,7 +104,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), action.host(), protocol.port()); + .newHandler(channel.alloc(), host, protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 0acf223eb9e..58c395ad86e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -17,37 +17,36 @@ import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpResponse; import javax.inject.Inject; /** - * Subclass of {@link MessageHandler} that converts inbound {@link FullHttpResponse} + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection + * in case of reuse for redirection. */ -public class WebWhoisMessageHandler extends MessageHandler { - - private HttpRequestMessage request; +public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject public WebWhoisMessageHandler() {} - /** Retains {@link HttpRequestMessage} and calls super write method*/ + /** Retains {@link HttpRequestMessage} and calls super write method. */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - request = (HttpRequestMessage) msg; + HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance */ + /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; - InboundMessageType response = HttpResponseMessage.fromResponse(originalResponse); + HttpResponseMessage response = new HttpResponseMessage(originalResponse); super.channelRead(ctx, response); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b06938d80a1..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,19 +19,30 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); @@ -39,18 +50,29 @@ public HttpRequestMessage setUri(String path) { } /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; - ByteBuf buf = request.content(); + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; - request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + } else { + throw new IllegalArgumentException(); + } + } - return finalRequest; + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 283b14440ac..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -34,17 +34,9 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index 2d5df10f8c1..be6c872cc3e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,7 +14,16 @@ package google.registry.monitoring.blackbox.messages; +import google.registry.monitoring.blackbox.exceptions.InternalException; + /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ -public interface OutboundMessageType {} +public interface OutboundMessageType { + + /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ + public OutboundMessageType modifyMessage(String... args) throws InternalException; + + /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ + public String name(); +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dab5851e8d8..dd1882b5686 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,18 +14,16 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.ProbingSequence; -import google.registry.monitoring.blackbox.ProbingStep; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link ProbingStep} - * in a single loop of a {@link ProbingSequence}. + * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} + * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link ProbingSequence}. Additionally, passes + * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes * on channel that remains unchanged within a loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop @@ -33,21 +31,17 @@ */ public abstract class Token { - /** - * {@link Channel} that always starts out as null. Once a persistent connection - * is made (such as EPP), that channel is stored in the token and passed on to - * later steps in the sequence until a new loop begins. - */ + /** {@link Channel} that always starts out as null. */ protected Channel channel; /** Obtains next {@link Token} for next loop in sequence. */ public abstract Token next(); /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String host(); + public abstract String getHost(); /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws UndeterminedStateException; + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; /** Set method for {@code channel} */ public void setChannel(Channel channel) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index bb06ee89db6..2847e5ce0eb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; -import java.util.LinkedList; +import java.util.List; import javax.inject.Inject; import javax.inject.Named; @@ -33,38 +33,42 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final static String PREFIX = "whois.nic."; + private final String prefix; /** {@link ImmutableList} of all top level domains to be probed. */ - private final Iterator topLevelDomainsIterator; + private final ImmutableList topLevelDomains; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private String currentDomain; + private int domainsIndex; @Inject - public WebWhoisToken(@WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken( + @Named("Web-WHOIS-Prefix") String prefix, + @WebWhoisProtocol ImmutableList topLevelDomains) { - topLevelDomainsIterator = topLevelDomains.iterator(); - currentDomain = topLevelDomainsIterator.next(); + domainsIndex = 0; + this.prefix = prefix; + this.topLevelDomains = topLevelDomains; } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + domainsIndex += 1; + domainsIndex %= topLevelDomains.size(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { - return original.modifyMessage(host()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { + return original.modifyMessage(getHost()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String host() { - return PREFIX + currentDomain; + public String getHost() { + return prefix + topLevelDomains.get(domainsIndex); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Mon, 29 Jul 2019 12:04:58 -0400 Subject: [PATCH 263/337] Minor Style Fixes --- .../monitoring/blackbox/ProbingAction.java | 85 ++++++++++--------- .../monitoring/blackbox/ProbingStep.java | 8 +- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..3f6a962b12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -89,11 +90,47 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** The {@link SocketAddress} instance that specifies remote address of connection */ + @Nullable public abstract SocketAddress address(); /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ public abstract Optional bootstrap(); + + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> actionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** * The method that performs the work of the actual action. * @@ -130,41 +167,13 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } @@ -224,7 +233,7 @@ public abstract static class Builder { abstract Channel channel(); - abstract Optional address(); + abstract SocketAddress address(); abstract Optional bootstrap(); @@ -233,7 +242,7 @@ public abstract static class Builder { abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) + if (address() == null) //If no address has been supplied, we set it based on the host and port setAddress(new InetSocketAddress(host(), protocol().port())); @@ -259,7 +268,7 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap().get().connect(address()); setChannel(connectionFuture.channel()); setConnectionFuture(connectionFuture); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index d54acef325a..47c89c72c11 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -21,7 +21,9 @@ import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import java.net.SocketAddress; import java.util.function.Consumer; +import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -48,6 +50,7 @@ public abstract class ProbingStep implements Consumer { abstract Protocol protocol(); abstract OutboundMessageType messageTemplate(); abstract Bootstrap bootstrap(); + @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -60,6 +63,8 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); + public abstract Builder setAddress(SocketAddress address); + public abstract ProbingStep build(); } @@ -87,7 +92,8 @@ private ProbingAction generateAction(Token token) throws InternalException { .setProtocol(protocol()) .setOutboundMessage(message) .setHost(token.getHost()) - .setBootstrap(bootstrap()); + .setBootstrap(bootstrap()) + .setAddress(address()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); From b4a583081eba35970156f6747d5b833d007a076d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:05:59 -0400 Subject: [PATCH 264/337] Updated build.gradle file --- prober/build.gradle | 8 - .../blackbox/ProbingSequenceStepTest.java | 219 ------------------ .../blackbox/ProbingSequenceTest.java | 96 -------- .../monitoring/blackbox/ProbingStepTest.java | 196 ++++++++-------- 4 files changed, 102 insertions(+), 417 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java diff --git a/prober/build.gradle b/prober/build.gradle index b23314728e1..bb3b59ce8d7 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,8 +16,6 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - - dependencies { def deps = rootProject.dependencyMap @@ -46,7 +44,6 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -55,8 +52,3 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } - -task(runMain, dependsOn: 'classes', type: JavaExec) { - main = 'google.registry.monitoring.blackbox.Prober' - classpath = sourceSets.main.runtimeClasspath -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java deleted file mode 100644 index 7a713017072..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.TestUtils.TestStep; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.handlers.ConversionHandler; -import google.registry.monitoring.blackbox.handlers.NettyRule; -import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; -import org.junit.Rule; -import org.junit.Test; - -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { - - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ - private ProbingSequence testSequence; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); - dummyStep = new DummyStep(testProtocol, eventLoopGroup); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(false) - .build(); - } - - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(true) - .build(); - } - - /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ - private void setupSequence() { - testSequence = new ProbingSequence.Builder() - .eventLoopGroup(eventLoopGroup) - .setClass(LocalChannel.class) - .addStep(firstStep) - .makeFirstRepeated() - .addStep(dummyStep) - .build(); - } - - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.nextStep()).isNull(); - - //we expect that this exception be thrown - assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); - - } - - @Test - public void testWithSequence_NewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupSequence(); - setupNewChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupSequence(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 5c4452df7b3..2b0559514a2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,101 +1,5 @@ -// Copyright 2019 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.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doCallRealMethod; - -import google.registry.monitoring.blackbox.tokens.Token; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) public class ProbingSequenceTest { - - private ProbingStep setupMock() { - ProbingStep mock = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(mock).nextStep(); - return mock; - } - - private static class Wrapper { - - T data; - - public Wrapper(T data) { - this.data = data; - } - } - - @Test - public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(firstStep) - .addStep(secondStep) - .addStep(thirdStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(thirdStep); - assertThat(thirdStep.nextStep()).isEqualTo(firstStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - - @Test - public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); - - Token testToken = Mockito.mock(Token.class); - - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(thirdStep) - .addStep(secondStep) - .markFirstRepeated() - .addStep(firstStep) - .build(); - - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(firstStep); - assertThat(thirdStep.nextStep()).isEqualTo(secondStep); - - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); - - sequence.start(); - - assertThat(wrapper.data).isTrue(); - } - } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 1f09dd13553..090753014e4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,59 +11,57 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.TestUtils.dummyStep; +import static google.registry.monitoring.blackbox.TestUtils.testStep; +import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; -import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; -import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingStepTest { +public class ProbingSequenceStepTest { /** Basic Constants necessary for tests */ - private final static String ADDRESS_NAME = "TEST_ADDRESS"; - private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final static int PROTOCOL_PORT = 0; - private final static String TEST_MESSAGE = "TEST_MESSAGE"; - private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -74,106 +72,117 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** - * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} - * is called, it just marks the supplied future as succeeded, returning the requisite token. - */ - private ProbingStep dummyStep() { - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(dummyStep).nextStep(); - return dummyStep; + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); } + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } - @Test - public void testNewChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); + dummyStep = dummyStep(eventLoopGroup); - // Sets up Protocol for when we create a new channel. - Protocol testProtocol = Protocol.builder() + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); + } - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) .build(); + } - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); + //there should be no next step + assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); - //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(address); + } + + @Test + public void testNewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //checks that we have appropriately sent the write message to server - nettyRule.assertReceivedMessage(TEST_MESSAGE); + nettyRule.assertThatCustomWorks(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - verify(dummyStep, times(1)).accept(any(Token.class)); + assertThat(future.get()).isEqualTo(testToken); + } - @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - - // Sets up Protocol for when a channel already exists. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) - .build(); - - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() - .setBootstrap(bootstrap) - .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) - .setProtocol(testProtocol) - .build(); - - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); - - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - - //Assures that the channel has a succeeded connectionFuture. - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, ""); + //setup + setupExistingProtocol(); + setupSteps(); + setupChannel(); + setupExistingChannelToken(); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -182,21 +191,20 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); - Object msg = channel.readOutbound(); - - while (msg == null) { - msg = channel.readOutbound(); - } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked - // as a success - verify(dummyStep, times(1)).accept(any(Token.class)); + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); } } From b5db3558cf049af6d90df55a0d8c94f37e3bc9e6 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 265/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From 23bd04ea438238e988e0f98ffef4d7c0efadf81b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:54:13 -0400 Subject: [PATCH 266/337] Updated WebWhois tests. --- .../blackbox/ProbingActionTest.java | 56 +++--- .../blackbox/ProbingSequenceTest.java | 183 ++++++++++++++++++ .../monitoring/blackbox/ProbingStepTest.java | 3 +- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 93 +++++++-- .../monitoring/blackbox/TokenTest.java | 13 +- .../blackbox/handlers/ConversionHandler.java | 2 +- .../blackbox/handlers/NettyRule.java | 12 +- .../handlers/SslClientInitializerTest.java | 46 ++--- .../blackbox/handlers/TestActionHandler.java | 6 +- .../handlers/WebWhoisActionHandlerTest.java | 159 ++++++++------- 11 files changed, 422 insertions(+), 157 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index cbcf2fc82b0..162044c2036 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -83,31 +84,31 @@ public class ProbingActionTest { /** Sets up a {@link Protocol} corresponding to when a new connection is created */ private void setupNewChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(false) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) .build(); } /** Sets up a {@link Protocol} corresponding to when a new connection exists */ private void setupExistingChannelProtocol() { protocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(TEST_PORT) - .persistentConnection(true) + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(true) .build(); } - /** Sets up a {@link NewChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ private void setupNewChannelAction() { - newChannelAction = NewChannelAction.builder() - .bootstrap(bootstrap) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") - .address(address) + newChannelAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") + .setAddress(address) .build(); } @@ -115,25 +116,25 @@ private void setupChannel() { channel = new EmbeddedChannel(); } - /** Sets up a {@link ExistingChannelAction} with test specified attributes */ + /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ExistingChannelAction.builder() - .channel(channel) - .protocol(protocol) - .delay(Duration.ZERO) - .outboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .host("") + existingChannelAction = ProbingAction.builder() + .setChannel(channel) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost("") .build(); } @Test - public void testBehavior_existingChannel() { + public void testBehavior_existingChannel() throws InternalException { //setup setupChannel(); setupExistingChannelProtocol(); - setupExistingChannelAction(channel); channel.pipeline().addLast(conversionHandler); channel.pipeline().addLast(testHandler); + setupExistingChannelAction(channel); ChannelFuture future = existingChannelAction.call(); @@ -147,6 +148,7 @@ public void testBehavior_existingChannel() { //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -156,9 +158,9 @@ public void testBehavior_existingChannel() { public void testSuccess_newChannel() throws Exception { //setup setupNewChannelProtocol(); - setupNewChannelAction(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + setupNewChannelAction(); ChannelFuture future = newChannelAction.call(); //Tests to see if message is properly sent to remote server diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2b0559514a2..681a5346d55 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,5 +1,188 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; + +import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; +import java.net.SocketAddress; +import org.joda.time.Duration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) public class ProbingSequenceTest { + private final static String TEST_HOST = "TEST_HOST"; + + + private Bootstrap dummyBootstrap = new Bootstrap(); + private Token testToken = new ProbingSequenceTestToken(); + + /** + * Custom {@link ProbingStep} subclass that acts as a mock + * step, so we can test how well {@link ProbingSequence} builds + * a linked list of {@link ProbingStep}s from their {@link Builder}s. + */ + private static class TestStep extends ProbingStep { + private Bootstrap bootstrap; + private String marker; + + /** We implement all abstract methods to simply return null, as we have no use for them here. */ + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + SocketAddress address() { + return null; + } + + /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ + @Override + Bootstrap bootstrap() { + return bootstrap; + } + + /** + * Builder for {@link TestStep}, that extends {@link ProbingStep.Builder} so that these can be + * input into the {@link ProbingSequence.Builder}. + */ + public static class Builder extends ProbingStep.Builder { + /** We test to see if we accurately add the right bootstrap to all {@link ProbingStep}s/ */ + private Bootstrap bootstrap; + + /** We also mark each step in order to ensure that when running, they are arranged in the right order. */ + private String marker; + + @Override + public ProbingStep.Builder setDuration(Duration value) { + return this; + } + + @Override + public ProbingStep.Builder setProtocol(Protocol value) { + return this; + } + + @Override + public ProbingStep.Builder setMessageTemplate(OutboundMessageType value) { + return null; + } + + @Override + public ProbingStep.Builder setAddress(SocketAddress address) { + return null; + } + + @Override + public ProbingStep.Builder setBootstrap(Bootstrap value) { + bootstrap = value; + return this; + } + + public ProbingStep.Builder addMarker(String value) { + marker = value; + return this; + } + + @Override + public ProbingStep build() { + return new TestStep(bootstrap, marker); + } + } + private TestStep(Bootstrap bootstrap, String marker) { + this.bootstrap = bootstrap; + this.marker = marker; + } + + /** + * On a call to accept, we modify the token to reflect what the current step is, so we can get + * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated + * in order. + */ + @Override + public void accept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + if (!isLastStep) { + nextStep().accept(token); + } else { + ((TestStep)nextStep()).specialAccept(token); + } + } + + /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ + public void specialAccept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + return; + } + } + + @Test + public void testSequenceBasicConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("firstsecondthirdfirst"); + } + + @Test + public void testSequenceAdvancedConstruction_Success() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + + ProbingSequence sequence = new ProbingSequence.Builder() + .setBootstrap(dummyBootstrap) + .addStep(thirdStepBuilder) + .addStep(secondStepBuilder) + .markFirstRepeated() + .addStep(firstStepBuilder) + .addToken(testToken) + .build(); + + sequence.start(); + + assertThat(testToken.getHost()).isEqualTo("thirdsecondfirstsecond"); + } + @Test + public void testSequenceConstruction_Failure() { + ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); + ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); + ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); + assertThrows(AssertionError.class, () -> { + ProbingSequence sequence = new ProbingSequence.Builder() + .addStep(firstStepBuilder) + .addStep(secondStepBuilder) + .addStep(thirdStepBuilder) + .addToken(testToken) + .setBootstrap(dummyBootstrap) + .build(); + }); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 090753014e4..ee38e7cdf74 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -21,7 +21,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; @@ -47,7 +46,7 @@ import org.junit.Test; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { +public class ProbingStepTest { /** Basic Constants necessary for tests */ private final String ADDRESS_NAME = "TEST_ADDRESS"; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 06b19ea3607..337d755e971 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -93,11 +93,11 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { HttpRequest request = (HttpRequest) msg; HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); } else if (request.headers().get("host").equals(destinationInput)) { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { - response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } ctx.channel().writeAndFlush(response); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 8d1722c9625..161304c1f04 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -17,9 +17,11 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -37,6 +39,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; +import java.net.Socket; +import java.net.SocketAddress; +import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -141,26 +146,67 @@ public DuplexMessageTest(String msg) { public String toString() { return message; } + + @Override + public OutboundMessageType modifyMessage(String... args) throws InternalException { + message = args[0]; + return this; + } + + @Override + public String name() { + return "Test Message of: " + this.toString(); + } } /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static class TestStep extends ProbingStep { + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .setAddress(address) + .build(); - public TestStep(Protocol protocol, String testMessage, LocalAddress address) { - super(protocol, new DuplexMessageTest(testMessage)); - this.address = address; - this.duration = Duration.ZERO; - } + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); } /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { + public static class DummyStep extends ProbingStep { private DefaultPromise future; - public DummyStep(Protocol protocol, EventLoopGroup eventLoopGroup) { - super(protocol, new DuplexMessageTest()); - future = new DefaultPromise(eventLoopGroup.next()) {}; - duration = Duration.ZERO; + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; + } + + @Nullable + @Override + SocketAddress address() { + return null; } @Override @@ -170,11 +216,16 @@ public void accept(Token token) { public DefaultPromise getFuture() { return future; } + + @Override + public String toString() { + return "Dummy Step"; + } } /** Basic outline for {@link Token} instances to be used in tests */ private static abstract class TestToken extends Token { - private String host; + protected String host; protected TestToken(String host) { this.host = host; @@ -221,6 +272,22 @@ public Channel channel() { } } + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + /** * Compares two {@link FullHttpMessage} for equivalency. * diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..67963805733 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,10 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; @@ -34,20 +35,20 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..a8506a996a9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -37,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b6b5e8fbe0c..b38c1911940 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; - -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.testing.JUnitBackports.assertThrows; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; @@ -89,7 +90,8 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { /** Sets up a client channel connecting to the give local address. */ void setUpClient( LocalAddress localAddress, - ProbingAction probingAction, + Protocol protocol, + String host, ChannelHandler handler) { checkState(echoHandler != null, "Must call setUpServer before setUpClient"); checkState(dumpHandler == null, "Can't call setUpClient twice"); @@ -109,7 +111,9 @@ protected void initChannel(LocalChannel ch) throws Exception { .group(eventLoopGroup) .channel(LocalChannel.class) .handler(clientInitializer) - .attr(PROBING_ACTION_KEY, probingAction); + .attr(PROTOCOL_KEY, protocol) + .attr(REMOTE_ADDRESS_KEY, host); + channel = b.connect(localAddress).syncUninterruptibly().channel(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 469c62a8f75..83c8e132f07 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -15,17 +15,18 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.getKeyPair; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.setUpSslChannel; import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ExistingChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; @@ -45,7 +46,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLException; -import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,8 +67,6 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - private static final OutboundMessageType DEFAULT_MESSAGE = new DuplexMessageTest("TEST_MESSAGE"); - /** Fake host to test if the SSL engine gets the correct peer host. */ private static final String SSL_HOST = "www.example.tld"; @@ -93,15 +91,12 @@ public static SslProvider[] data() { private String sniHostReceived; /** Fake protocol saved in channel attribute. */ - private static final Protocol PROTOCOL = - Protocol.builder() - .name("ssl") - .port(SSL_PORT) - .handlerProviders(ImmutableList.of()) - .persistentConnection(false) - .build(); - - private ProbingAction probingAction; + private final static Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { @@ -113,23 +108,13 @@ private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate c }); } - private void setupProbingAction(Channel channel) { - probingAction = ExistingChannelAction.builder() - .delay(Duration.ZERO) - .host(SSL_HOST) - .channel(channel) - .outboundMessage(DEFAULT_MESSAGE) - .protocol(PROTOCOL) - .build(); - } - @Test public void testSuccess_swappedInitializerWithSslHandler() throws Exception { SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); EmbeddedChannel channel = new EmbeddedChannel(); - setupProbingAction(channel); - channel.attr(PROBING_ACTION_KEY).set(probingAction); + channel.attr(PROTOCOL_KEY).set(PROTOCOL); + channel.attr(REMOTE_ADDRESS_KEY).set(SSL_HOST); ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(sslClientInitializer); ChannelHandler firstHandler = pipeline.first(); @@ -160,8 +145,7 @@ public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Except SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // The connection is now terminated, both the client side and the server side should get // exceptions. nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class); @@ -189,8 +173,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); setUpSslChannel(nettyRule.getChannel(), cert); nettyRule.assertThatMessagesWork(); @@ -219,8 +202,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E SslClientInitializer sslClientInitializer = new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); - setupProbingAction(new EmbeddedChannel()); - nettyRule.setUpClient(localAddress, probingAction, sslClientInitializer); + nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); // When the client rejects the server cert due to wrong hostname, both the client and server // should throw exceptions. diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 518bb9ba686..e170fad8b8c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox.handlers; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from * parent class other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index d8a672758da..72d5d5078df 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,21 +15,21 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPromise; @@ -65,6 +65,14 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; + private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); + private static final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of()) + .setName("test_protocol") + .setPersistentConnection(false) + .setPort(HTTPS_PORT) + .build(); + private LocalAddress address; private EmbeddedChannel channel; @@ -75,30 +83,38 @@ public class WebWhoisActionHandlerTest { private void generateLocalAddress() { address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); } + /** Creates default protocol with empty list of handlers and specified other inputs */ - private Protocol createProtocol(String name, int port) { + private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() - .name(name) - .port(port) - .handlerProviders(ImmutableList.of(actionHandlerProvider)) - .persistentConnection(false) + .setName(name) + .setPort(port) + .setHandlerProviders(ImmutableList.of(actionHandlerProvider)) + .setPersistentConnection(persistentConnection) .build(); } /** Initializes new WebWhoisActionHandler */ - private void setupActionHandler() { - actionHandler = new WebWhoisActionHandler(); + private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { + actionHandler = new WebWhoisActionHandler( + bootstrap, + STANDARD_PROTOCOL, + STANDARD_PROTOCOL, + messageTemplate, + 80, + 443 + ); actionHandlerProvider = new TestProvider<>(actionHandler); } /** Sets up testing channel with requisite attributes */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + channel = new EmbeddedChannel(actionHandler); + channel.attr(PROTOCOL_KEY).set(protocol); setupProbingActionBasic( protocol, outboundMessage, makeBootstrap(new NioEventLoopGroup(1))); - channel = new EmbeddedChannel(actionHandler); - channel.attr(PROBING_ACTION_KEY).set(probingAction); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -108,24 +124,25 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { } /**Sets up probingAction for when testing redirection */ private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(TARGET_HOST) - .address(DEFAULT_ADDRESS) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(TARGET_HOST) + .setAddress(DEFAULT_ADDRESS) + .setChannel(channel) .build(); } private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { - probingAction = NewChannelAction.builder() - .protocol(protocol) - .outboundMessage(outboundMessage) - .delay(DEFAULT_DURATION) - .bootstrap(bootstrap) - .host(host) - .address(address) + probingAction = ProbingAction.builder() + .setProtocol(protocol) + .setOutboundMessage(outboundMessage) + .setDelay(DEFAULT_DURATION) + .setBootstrap(bootstrap) + .setHost(host) + .setAddress(address) .build(); } @@ -136,10 +153,13 @@ private void setupLocalServer(String redirectInput, String destinationInput, Eve @Test public void testBasic_responseOk() throws Exception { //setup - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, true); generateLocalAddress(); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); + + setupChannel(initialProtocol, msg); //stores future @@ -151,7 +171,7 @@ public void testBasic_responseOk() throws Exception { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeHttpResponse(HttpResponseStatus.OK)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); //assesses that future listener isn't triggered yet. @@ -161,15 +181,16 @@ public void testBasic_responseOk() throws Exception { //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseFailure() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseBad", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseBad", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -181,8 +202,7 @@ public void testBasic_responseFailure() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage - .fromResponse(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -194,14 +214,15 @@ public void testBasic_responseFailure() { assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_responseError() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseError", 0); + Bootstrap bootstrap = null; + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseError", 0, true); generateLocalAddress(); setupChannel(initialProtocol, msg); @@ -213,7 +234,7 @@ public void testBasic_responseError() { ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); //assesses that future listener isn't triggered yet. assertThat(testPromise.isSuccess()).isFalse(); @@ -224,27 +245,30 @@ public void testBasic_responseError() { assertThat(testPromise.isSuccess()).isTrue(); assertThat(future.isSuccess()).isTrue(); //ensures Protocol is the same - assertThat(channel.attr(PROBING_ACTION_KEY).get()).isEqualTo(probingAction); + assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test public void testBasic_redirectCloseChannel() { //setup - HttpRequestMessage outboundMessage = HttpRequestMessage.fromRequest(makeHttpGetRequest("", "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", 0); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", 0, true); generateLocalAddress(); - setupChannel(initialProtocol, outboundMessage); + setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFuture(); - channel.writeOutbound(outboundMessage); + channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early ChannelPromise testPromise = channel.newPromise(); future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); //checks that future has not been set to successful or a failure assertThat(testPromise.isSuccess()).isFalse(); @@ -260,12 +284,15 @@ public void testBasic_redirectCloseChannel() { @Test public void testBasic_redirectHost() { //setup - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT); + Bootstrap bootstrap = new Bootstrap() + .group(new NioEventLoopGroup(1)) + .channel(LocalChannel.class); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); generateLocalAddress(); setupChannel(initialProtocol, msg); - HttpResponse originalResponse = HttpResponseMessage.fromResponse(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); //store future @@ -275,27 +302,24 @@ public void testBasic_redirectHost() { channel.writeInbound(originalResponse); - ProbingAction newAction = channel.attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - //gets changed protocol - Protocol newProtocol = newAction.protocol(); //ensures that the new protocol has host and port specified by redirection assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - assertThat(newAction.host()).isEqualTo(REDIRECT_HOST); - assertThat(newAction.path()).isEqualTo(REDIRECT_PATH); } @Test - public void testAdvanced_responseOk() { + public void testAdvanced_responseOk() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); //stores future ChannelFuture future = probingAction.call(); @@ -305,15 +329,16 @@ public void testAdvanced_responseOk() { } @Test - public void testAdvanced_responseFailure() { + public void testAdvanced_responseFailure() throws InternalException { //setup + Bootstrap bootstrap = null; EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = HttpRequestMessage.fromRequest(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(); - Protocol initialProtocol = createProtocol("responseOk", 0); + HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); + setupActionHandler(bootstrap, msg); + Protocol initialProtocol = createProtocol("responseOk", 0, false); generateLocalAddress(); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); setupLocalServer("", TARGET_HOST, group); + setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); //stores future ChannelFuture future = probingAction.call(); From 634a4b90f8ef1e8106058f90608cafa6ca90aaa2 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:28:40 -0400 Subject: [PATCH 267/337] Added license header and newline where appropriate. --- prober/build.gradle | 1 + .../monitoring/blackbox/ProbingAction.java | 95 +++++++++---------- .../blackbox/handlers/ActionHandler.java | 92 ++++-------------- .../blackbox/ProbingSequenceTest.java | 14 +++ 4 files changed, 77 insertions(+), 125 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index bb3b59ce8d7..3652390d0ba 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -35,6 +35,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] + compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 3f6a962b12d..a8740e21c20 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,25 +14,29 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -65,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -80,31 +87,18 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - @Nullable - public abstract SocketAddress address(); - - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { // Write appropriate outboundMessage to pipeline ChannelFuture channelFuture = actionHandler.getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> actionHandler.resetFuture(), - //inform ProbingStep of the status of our action future -> { if (future.isSuccess()) @@ -141,7 +135,7 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -154,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -180,19 +174,24 @@ public ChannelFuture performAction() throws InternalException { /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -210,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -221,40 +226,29 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract SocketAddress address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (address() == null) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -268,14 +262,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -293,7 +284,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index e397393b4e9..8a108b81006 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -14,13 +14,11 @@ package google.registry.monitoring.blackbox.handlers; -import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -33,7 +31,7 @@ * messages that implement the {@link InboundMessageType} interface.

* *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link google.registry.monitoring.blackbox.ProbingAction} in charge that a response has been read. + * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

@@ -44,111 +42,59 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler logger.atInfo().log("Unsuccessful channel connection closed")); - - } else if (cause instanceof InternalException){ - //For an internal error, metrics should not be collected, so we log what caused this, and - //inform the ProbingStep the Prober had an internal error on this action - logger.atSevere().withCause(cause).log("Severe internal error"); finished.setFailure(cause); - - //As this was an internal error, we must close the channel - ChannelFuture closedFuture = ctx.channel().close(); - closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); - } else { - //In the case of any other kind of error, we assume it is some type of connection ERROR, - //so we treat it as such: + //On UndeterminedStateException, we know the response type is an error. - status = ResponseType.ERROR; - - logger.atInfo().log(cause.getMessage()); - finished.setSuccess(); + //Since it wasn't a success, we still log what caused the ERROR + logger.atWarning().log(cause.getMessage()); + finished.setFailure(cause); + //As this was an ERROR in performing the action, we must close the channel ChannelFuture closedFuture = ctx.channel().close(); closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed")); } - - - - } - - /**Only exists for testing purposes to see if {@link ActionHandler} displays the expected status's from responses. */ - @VisibleForTesting - ResponseType getStatus() { - return status; } } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 681a5346d55..fee4de802da 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; From 770463b0a0e1e4c28eb3c7c658cb4bde6e10e5df Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 268/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/ProbingStepTest.java | 1 - .../blackbox/TestServers/WebWhoisServer.java | 3 +- .../monitoring/blackbox/TestUtils.java | 35 +------------------ .../blackbox/handlers/ConversionHandler.java | 5 ++- .../blackbox/handlers/NettyRule.java | 4 ++- 5 files changed, 10 insertions(+), 38 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index ee38e7cdf74..c98c6414f29 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -172,7 +172,6 @@ public void testNewChannel() throws Exception { //checks that when the future is successful, we pass down the requisite token assertThat(future.get()).isEqualTo(testToken); - } @Test diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 337d755e971..e7f125bb906 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; @@ -80,7 +81,7 @@ static class RedirectHandler extends ChannelDuplexHandler { /** * * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus.OK} response when receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 161304c1f04..72e0f1f7f71 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.InternalException; @@ -30,18 +29,14 @@ import io.netty.channel.local.LocalChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpMethod;; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.concurrent.DefaultPromise; import java.net.Socket; import java.net.SocketAddress; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -287,33 +282,5 @@ public void addToHost(String suffix) { } } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index a8506a996a9..196141bb875 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index b38c1911940..1d14cf131e6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -26,6 +26,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.ProbingActionTest; +import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; @@ -54,7 +56,7 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingSequenceStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { From 0c026d8dd16eb3f956b86346f76a53ad49a72fbc Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 5 Aug 2019 16:16:36 -0400 Subject: [PATCH 269/337] Refactored ProbingAction to minimize number of unnecessary methods --- .../registry/monitoring/blackbox/Prober.java | 10 +- .../monitoring/blackbox/ProberModule.java | 15 +- .../monitoring/blackbox/ProbingAction.java | 160 ++++++++---------- .../monitoring/blackbox/ProbingStep.java | 55 +++--- .../monitoring/blackbox/WebWhoisModule.java | 49 +++--- .../blackbox/handlers/ActionHandler.java | 2 +- .../handlers/WebWhoisActionHandler.java | 56 +++--- .../blackbox/messages/HttpRequestMessage.java | 7 +- .../blackbox/ProbingActionTest.java | 133 +++++++-------- .../blackbox/ProbingSequenceTest.java | 133 +++++---------- .../monitoring/blackbox/ProbingStepTest.java | 6 + .../monitoring/blackbox/TestUtils.java | 2 +- .../handlers/WebWhoisActionHandlerTest.java | 9 +- 13 files changed, 288 insertions(+), 349 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..e12d1f0f522 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,7 +14,9 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +30,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.sequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index 0daaf16ded4..fb83b236b69 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,14 +14,18 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; +import java.util.Set; import javax.inject.Singleton; import org.joda.time.Duration; @@ -33,7 +37,7 @@ public class ProberModule { /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ - private static final Duration DEFAULT_DURATION = new Duration(4000L); + private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ @Provides @@ -42,6 +46,12 @@ EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } + /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + @Provides + @Singleton + Class provideChannelClazz() { + return NioSocketChannel.class; + } /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ @Provides @Singleton @@ -51,6 +61,7 @@ Duration provideDuration() { /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ @Provides + @Singleton static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; @@ -66,7 +77,7 @@ static SslProvider provideSslProvider() { public interface ProberComponent { //Standard WebWhois sequence - @WebWhoisProtocol ProbingSequence provideWebWhoisSequence(); + Set sequences(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index a8740e21c20..25c3a1c17d6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -33,10 +33,8 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -69,6 +67,8 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -85,6 +85,7 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ @@ -94,108 +95,89 @@ public abstract class ProbingAction implements Callable { public abstract String host(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } - /** - * The method that performs the work of the actual action. + * Performs the work of the actual action * - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ *

First, checks if channel is active by setting a listener to perform the bulk of the work + * when the connection future is successful.

+ * + *

Once the connection is successful, we establish which of the handlers in the pipeline is + * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when + * we receive an expected response from the server.

+ * + *

Next, we set a timer set to a specified delay. After the delay has passed, we send the + * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, + * we inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - - //ChannelPromise that we use to inform ProbingStep when we are finished. - ChannelPromise finished = channel().newPromise(); - - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - - return finished; - } /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws UndeterminedStateException { + public ChannelFuture call() { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); + + //Ensures channel has been set up with connection future as an attribute + checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + //When connection is established call super.call and set returned listener to success channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { + (ChannelFuture connectionFuture) -> { + if (connectionFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); + ActionHandler actionHandler; + try { + actionHandler = channel().pipeline().get(ActionHandler.class); + } catch (ClassCastException e) { + //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); + } + + ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> { + if (future.isSuccess()) { + finished.setSuccess(); + } else { + finished.setFailure(future.cause()); + } + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) { + logger.atInfo() + .log("Closed stale channel. Moving on to next ProbingStep"); + } else { + logger.atWarning() + .log( + "Could not close channel. Stale connection still exists."); + } + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); } else { //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( + logger.atSevere().withCause(connectionFuture.cause()).log( "Cannot connect to relay channel for %s channel: %s.", protocol().name(), this.channel()); ChannelFuture unusedFuture = channel().close(); @@ -228,7 +210,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract Protocol protocol(); - abstract Optional channel(); + abstract Channel channel(); abstract String host(); @@ -243,11 +225,11 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { + if (channel() == null) { bootstrap.handler( new ChannelInitializer() { @Override diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 47c89c72c11..3df536a9478 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,14 +16,12 @@ import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; -import java.net.SocketAddress; import java.util.function.Consumer; -import javax.annotation.Nullable; import org.joda.time.Duration; /** @@ -39,18 +37,23 @@ @AutoValue public abstract class ProbingStep implements Consumer { - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /** Necessary boolean to inform when to obtain next {@link Token}*/ - private boolean isLastStep = false; + protected boolean isLastStep = false; private ProbingStep nextStep; + /** Time delay duration between actions. */ abstract Duration duration(); + + /** {@link Protocol} type for this step. */ abstract Protocol protocol(); + + /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ abstract OutboundMessageType messageTemplate(); + + /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ abstract Bootstrap bootstrap(); - @Nullable abstract SocketAddress address(); @AutoValue.Builder @@ -63,8 +66,6 @@ public static abstract class Builder { public abstract Builder setBootstrap(Bootstrap value); - public abstract Builder setAddress(SocketAddress address); - public abstract ProbingStep build(); } @@ -85,18 +86,18 @@ ProbingStep nextStep() { } /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws InternalException { + private ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) .setProtocol(protocol()) .setOutboundMessage(message) - .setHost(token.getHost()) - .setBootstrap(bootstrap()) - .setAddress(address()); + .setHost(token.host()); if (token.channel() != null) probingActionBuilder.setChannel(token.channel()); + else + probingActionBuilder.setBootstrap(bootstrap()); return probingActionBuilder.build(); } @@ -107,44 +108,58 @@ private Token generateNextToken(Token token) { return (isLastStep) ? token.next() : token; } + /** + * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. + * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

+ */ @Override public void accept(Token token) { ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = generateAction(token); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); nextStep.accept(generateNextToken(token)); return; } - - //call the created action ChannelFuture future; - try { + //call the generated action future = currentAction.call(); - - } catch(InternalException e) { + } catch(Exception e) { + //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); + + //Move on to next step in ProbingSequence nextStep.accept(generateNextToken(token)); return; } - //On result, either log success and move on, or future.addListener(f -> { if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - //If the next step maintains the connection, pass on the channel from this + } else { + //On a failed result, we log the failure and note either a failure or error logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } + if (protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token token.setChannel(currentAction.channel()); + //Move on the the next step in the ProbingSequence nextStep.accept(generateNextToken(token)); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dcc9635beaa..2e640338511 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,6 +18,7 @@ import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; @@ -26,6 +27,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; @@ -44,11 +46,10 @@ @Module public class WebWhoisModule { - private final int httpWhoIsPort = 80; - private final int httpsWhoIsPort = 443; - private static final String HTTP_PROTOCOL_NAME = "whois_http"; - private static final String HTTPS_PROTOCOL_NAME = "whois_https"; - private static final String DOMAIN_PREFIX = "whois.nic."; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; + private static final String HTTP_PROTOCOL_NAME = "http"; + private static final String HTTPS_PROTOCOL_NAME = "https"; /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; @@ -68,16 +69,14 @@ public class WebWhoisModule { /** {@link Provides} standard WebWhois sequence. */ @Provides - @WebWhoisProtocol + @Singleton + @IntoSet ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep.Builder probingStepBuilder, - WebWhoisToken webWhoisToken, - @WebWhoisProtocol Bootstrap bootstrap) { + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { - return new ProbingSequence.Builder() - .addToken(webWhoisToken) - .setBootstrap(bootstrap) - .addStep(probingStepBuilder) + return new ProbingSequence.Builder(webWhoisToken) + .addStep(probingStep) .build(); } @@ -85,15 +84,18 @@ ProbingSequence provideWebWhoisSequence( /** {@link Provides} only step used in WebWhois sequence. */ @Provides @WebWhoisProtocol - static ProbingStep.Builder provideWebWhoisStepBuilder( + static ProbingStep provideWebWhoisStep( @HttpWhoisProtocol Protocol httpWhoisProtocol, + @WebWhoisProtocol Bootstrap bootstrap, HttpRequestMessage messageTemplate, Duration duration) { return ProbingStep.builder() .setProtocol(httpWhoisProtocol) + .setBootstrap(bootstrap) .setMessageTemplate(messageTemplate) - .setDuration(duration); + .setDuration(duration) + .build(); } /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ @@ -126,13 +128,6 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - /** {@link Provides} the prefix where we probe: "prefix.tld". */ - @Provides - @Named("Web-WHOIS-Prefix") - String provideWhoisPrefix() { - return DOMAIN_PREFIX; - } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ @Provides @@ -187,10 +182,12 @@ static SslClientInitializer provideSslClientInitializer(SslPro @Singleton @Provides @WebWhoisProtocol - static Bootstrap provideBootstrap(EventLoopGroup eventLoopGroup) { + static Bootstrap provideBootstrap( + EventLoopGroup eventLoopGroup, + Class channelClazz){ return new Bootstrap() .group(eventLoopGroup) - .channel(NioSocketChannel.class); + .channel(channelClazz); } @Provides @@ -210,13 +207,13 @@ ImmutableList provideTopLevelDomains() { @Provides @HttpWhoisProtocol int provideHttpWhoisPort() { - return httpWhoIsPort; + return HTTP_WHOIS_PORT; } @Provides @HttpsWhoisProtocol int provideHttpsWhoisPort() { - return httpsWhoIsPort; + return HTTPS_WHOIS_PORT; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 8a108b81006..55c9123e3a5 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -46,7 +46,7 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..5e9300d0f34 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,15 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + String.format( + "Wrong number of arguments present for modifying HttpRequestMessage." + + " Received %d arguments instead of: " + args, args.length)); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index 162044c2036..b5d8f7599c4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -15,13 +15,14 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -38,6 +39,7 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.HashedWheelTimer; import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Rule; @@ -52,18 +54,13 @@ * */ @RunWith(JUnit4.class) public class ProbingActionTest { - /** Necessary Constants for test */ - private final String TEST_MESSAGE = "MESSAGE_TEST"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final int TEST_PORT = 0; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - private Bootstrap bootstrap = new Bootstrap() - .group(eventLoopGroup) - .channel(LocalChannel.class); + private static final String TEST_MESSAGE = "MESSAGE_TEST"; + private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; + private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private static final String ADDRESS_NAME = "TEST_ADDRESS"; + private static final int TEST_PORT = 0; + + private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ private ActionHandler testHandler = new TestActionHandler(); @@ -72,83 +69,51 @@ public class ProbingActionTest { private Provider testHandlerProvider = new TestProvider<>(testHandler); private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - private ProbingAction newChannelAction; - private ProbingAction existingChannelAction; - private EmbeddedChannel channel; - private Protocol protocol; - /** Used for testing how well probing step can create connection to blackbox server */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** Sets up a {@link Protocol} corresponding to when a new connection is created */ - private void setupNewChannelProtocol() { - protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(TEST_PORT) - .setPersistentConnection(false) - .build(); - } - /** Sets up a {@link Protocol} corresponding to when a new connection exists */ - private void setupExistingChannelProtocol() { - protocol = Protocol.builder() + + + + @Test + public void testBehavior_existingChannel() throws UndeterminedStateException { + //setup + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up a Protocol corresponding to when a connection exists. + Protocol protocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) .build(); - } - - /** Sets up a {@link ProbingAction} that creates a channel using test specified attributes. */ - private void setupNewChannelAction() { - newChannelAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(protocol) - .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) - .setHost("") - .setAddress(address) - .build(); - } - private void setupChannel() { - channel = new EmbeddedChannel(); - } - - /** Sets up a {@link ProbingAction} with existing channel using test specified attributes. */ - private void setupExistingChannelAction(Channel channel) { - existingChannelAction = ProbingAction.builder() + // Sets up a ProbingAction that creates a channel using test specified attributes. + ProbingAction action = ProbingAction.builder() .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) .setHost("") .build(); - } - - @Test - public void testBehavior_existingChannel() throws InternalException { - //setup - setupChannel(); - setupExistingChannelProtocol(); - channel.pipeline().addLast(conversionHandler); - channel.pipeline().addLast(testHandler); - setupExistingChannelAction(channel); - - ChannelFuture future = existingChannelAction.call(); + //tests main function of ProbingAction + ChannelFuture future = action.call(); - //Ensures that we pass in the right message to the channel and haven't marked the future as success yet - Object msg = channel.readOutbound(); + //Obtains the outboundMessage passed through pipeline after delay + Object msg = null; + while (msg == null) { + msg = channel.readOutbound(); + } + //tests the passed message is exactly what we expect assertThat(msg).isInstanceOf(ByteBuf.class); - String response = ((ByteBuf) msg).toString(UTF_8); - assertThat(response).isEqualTo(TEST_MESSAGE); - assertThat(future.isSuccess()).isFalse(); + String request = ((ByteBuf) msg).toString(UTF_8); + assertThat(request).isEqualTo(TEST_MESSAGE); //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - future.syncUninterruptibly(); assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(SECONDARY_TEST_MESSAGE); @@ -157,18 +122,40 @@ public void testBehavior_existingChannel() throws InternalException { @Test public void testSuccess_newChannel() throws Exception { //setup - setupNewChannelProtocol(); + + LocalAddress address = new LocalAddress(ADDRESS_NAME); + Bootstrap bootstrap = new Bootstrap() + .group(eventLoopGroup) + .channel(LocalChannel.class); + + // Sets up a Protocol corresponding to when a new connection is created. + Protocol protocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(TEST_PORT) + .setPersistentConnection(false) + .build(); nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - setupNewChannelAction(); - ChannelFuture future = newChannelAction.call(); + + // Sets up a ProbingAction with existing channel using test specified attributes. + ProbingAction action = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(protocol) + .setDelay(Duration.ZERO) + .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setHost(ADDRESS_NAME) + .build(); + + //tests main function of ProbingAction + ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server nettyRule.assertThatCustomWorks(TEST_MESSAGE); - future.sync(); + future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true - assertThat(future.isSuccess()); + assertThat(future.isSuccess()).isTrue(); assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index fee4de802da..e5f91a300d6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -18,30 +18,45 @@ import static google.registry.testing.JUnitBackports.assertThrows; import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.TestUtils.TestToken; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; import java.net.SocketAddress; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; @RunWith(JUnit4.class) public class ProbingSequenceTest { private final static String TEST_HOST = "TEST_HOST"; - private Bootstrap dummyBootstrap = new Bootstrap(); - private Token testToken = new ProbingSequenceTestToken(); + private Token testToken = new TestToken("") { + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + }; + private void setupMock(ProbingStep mock, ProbingStep nextStep) { + Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + } /** * Custom {@link ProbingStep} subclass that acts as a mock * step, so we can test how well {@link ProbingSequence} builds * a linked list of {@link ProbingStep}s from their {@link Builder}s. */ + private static class TestStep extends ProbingStep { - private Bootstrap bootstrap; private String marker; /** We implement all abstract methods to simply return null, as we have no use for them here. */ @@ -60,66 +75,13 @@ OutboundMessageType messageTemplate() { return null; } - @Override - SocketAddress address() { - return null; - } - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ @Override Bootstrap bootstrap() { - return bootstrap; + return null; } - /** - * Builder for {@link TestStep}, that extends {@link ProbingStep.Builder} so that these can be - * input into the {@link ProbingSequence.Builder}. - */ - public static class Builder extends ProbingStep.Builder { - /** We test to see if we accurately add the right bootstrap to all {@link ProbingStep}s/ */ - private Bootstrap bootstrap; - - /** We also mark each step in order to ensure that when running, they are arranged in the right order. */ - private String marker; - - @Override - public ProbingStep.Builder setDuration(Duration value) { - return this; - } - - @Override - public ProbingStep.Builder setProtocol(Protocol value) { - return this; - } - - @Override - public ProbingStep.Builder setMessageTemplate(OutboundMessageType value) { - return null; - } - - @Override - public ProbingStep.Builder setAddress(SocketAddress address) { - return null; - } - - @Override - public ProbingStep.Builder setBootstrap(Bootstrap value) { - bootstrap = value; - return this; - } - - public ProbingStep.Builder addMarker(String value) { - marker = value; - return this; - } - - @Override - public ProbingStep build() { - return new TestStep(bootstrap, marker); - } - } - private TestStep(Bootstrap bootstrap, String marker) { - this.bootstrap = bootstrap; + public TestStep(String marker) { this.marker = marker; } @@ -147,56 +109,37 @@ public void specialAccept(Token token) { @Test public void testSequenceBasicConstruction_Success() { - ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); - ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); - ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); - - ProbingSequence sequence = new ProbingSequence.Builder() - .setBootstrap(dummyBootstrap) - .addStep(firstStepBuilder) - .addStep(secondStepBuilder) - .addStep(thirdStepBuilder) - .addToken(testToken) + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + + ProbingSequence sequence = new ProbingSequence.Builder(testToken) + .addStep(firstStep) + .addStep(secondStep) + .addStep(thirdStep) .build(); sequence.start(); - assertThat(testToken.getHost()).isEqualTo("firstsecondthirdfirst"); + assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); - ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); - ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); - - ProbingSequence sequence = new ProbingSequence.Builder() - .setBootstrap(dummyBootstrap) - .addStep(thirdStepBuilder) - .addStep(secondStepBuilder) + ProbingStep firstStep = new TestStep("first"); + ProbingStep secondStep = new TestStep("second"); + ProbingStep thirdStep = new TestStep("third"); + + ProbingSequence sequence = new ProbingSequence.Builder(testToken) + .addStep(thirdStep) + .addStep(secondStep) .markFirstRepeated() - .addStep(firstStepBuilder) - .addToken(testToken) + .addStep(firstStep) .build(); sequence.start(); - assertThat(testToken.getHost()).isEqualTo("thirdsecondfirstsecond"); + assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); } - @Test - public void testSequenceConstruction_Failure() { - ProbingStep.Builder firstStepBuilder = new TestStep.Builder().addMarker("first"); - ProbingStep.Builder secondStepBuilder = new TestStep.Builder().addMarker("second"); - ProbingStep.Builder thirdStepBuilder = new TestStep.Builder().addMarker("third"); - assertThrows(AssertionError.class, () -> { - ProbingSequence sequence = new ProbingSequence.Builder() - .addStep(firstStepBuilder) - .addStep(secondStepBuilder) - .addStep(thirdStepBuilder) - .addToken(testToken) - .setBootstrap(dummyBootstrap) - .build(); - }); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index c98c6414f29..da262c52a74 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -44,6 +44,7 @@ import javax.inject.Provider; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ public class ProbingStepTest { @@ -189,6 +190,11 @@ public void testWithSequence_ExistingChannel() throws Exception { //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline firstStep.accept(testToken); + Object msg = channel.readOutbound(); + + while (msg == null) { + msg = channel.readOutbound(); + } //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 72e0f1f7f71..e9b74c969f2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -219,7 +219,7 @@ public String toString() { } /** Basic outline for {@link Token} instances to be used in tests */ - private static abstract class TestToken extends Token { + static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 72d5d5078df..e7930f69c7d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -39,7 +39,6 @@ import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; import org.joda.time.Duration; @@ -163,7 +162,7 @@ public void testBasic_responseOk() throws Exception { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); @@ -195,7 +194,7 @@ public void testBasic_responseFailure() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -227,7 +226,7 @@ public void testBasic_responseError() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early @@ -261,7 +260,7 @@ public void testBasic_redirectCloseChannel() { setupChannel(initialProtocol, msg); //stores future - ChannelFuture future = actionHandler.getFuture(); + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); //setup for checker to ensure future listener isn't triggered to early From ddf0daefe2f109a93d62a62c542c0b988b9f4368 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 15:45:32 -0400 Subject: [PATCH 270/337] Modified tests for WebWhois according to changes suggested by laijiang. --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProberModule.java | 2 - .../monitoring/blackbox/ProbingAction.java | 1 - .../monitoring/blackbox/WebWhoisModule.java | 10 +- .../blackbox/ProbingActionTest.java | 20 +- .../blackbox/ProbingSequenceTest.java | 120 +++------ .../monitoring/blackbox/ProbingStepTest.java | 187 +++++++------ .../blackbox/TestServers/TestServer.java | 38 --- .../blackbox/TestServers/WebWhoisServer.java | 6 +- .../monitoring/blackbox/TestUtils.java | 159 +----------- .../monitoring/blackbox/TokenTest.java | 61 ----- .../blackbox/handlers/ConversionHandler.java | 6 +- .../blackbox/handlers/NettyRule.java | 46 +++- .../handlers/SslClientInitializerTest.java | 5 - .../blackbox/handlers/TestActionHandler.java | 13 +- .../handlers/WebWhoisActionHandlerTest.java | 245 ++++++------------ .../blackbox/messages/TestMessage.java | 4 + 17 files changed, 273 insertions(+), 653 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index e12d1f0f522..5ca423c29cc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -30,7 +29,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.sequences(); + ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index fb83b236b69..f9db4865f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -14,11 +14,9 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableList; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 25c3a1c17d6..0265390fafe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -138,7 +138,6 @@ public ChannelFuture call() { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); timer.newTimeout(timeout -> { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 2e640338511..de041afad38 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,14 +17,11 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -33,10 +30,7 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index b5d8f7599c4..ec5ee5d77ec 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,17 +20,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -39,9 +37,9 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; import javax.inject.Provider; import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,10 +72,9 @@ public class ProbingActionTest { public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - + @Ignore @Test - public void testBehavior_existingChannel() throws UndeterminedStateException { + public void testBehavior_existingChannel() { //setup EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -95,7 +92,7 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { .setChannel(channel) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost("") .build(); @@ -112,6 +109,9 @@ public void testBehavior_existingChannel() throws UndeterminedStateException { String request = ((ByteBuf) msg).toString(UTF_8); assertThat(request).isEqualTo(TEST_MESSAGE); + // Ensures that we haven't marked future as done until response is received. + assertThat(future.isDone()).isFalse(); + //after writing inbound, we should have a success channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); assertThat(future.isSuccess()).isTrue(); @@ -143,7 +143,7 @@ public void testSuccess_newChannel() throws Exception { .setBootstrap(bootstrap) .setProtocol(protocol) .setDelay(Duration.ZERO) - .setOutboundMessage(new DuplexMessageTest(TEST_MESSAGE)) + .setOutboundMessage(new TestMessage(TEST_MESSAGE)) .setHost(ADDRESS_NAME) .build(); @@ -151,7 +151,7 @@ public void testSuccess_newChannel() throws Exception { ChannelFuture future = action.call(); //Tests to see if message is properly sent to remote server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index e5f91a300d6..5c4452df7b3 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -15,17 +15,11 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; -import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; -import google.registry.monitoring.blackbox.TestUtils.TestToken; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import java.net.SocketAddress; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,85 +27,31 @@ @RunWith(JUnit4.class) public class ProbingSequenceTest { - private final static String TEST_HOST = "TEST_HOST"; - private Token testToken = new TestToken("") { - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - }; - - private void setupMock(ProbingStep mock, ProbingStep nextStep) { - Mockito.when(mock.accept()).thenCallRealMethod(() -> System.out.println("test")); + private ProbingStep setupMock() { + ProbingStep mock = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(mock).nextStep(); + return mock; } - /** - * Custom {@link ProbingStep} subclass that acts as a mock - * step, so we can test how well {@link ProbingSequence} builds - * a linked list of {@link ProbingStep}s from their {@link Builder}s. - */ - - private static class TestStep extends ProbingStep { - private String marker; - - /** We implement all abstract methods to simply return null, as we have no use for them here. */ - @Override - Duration duration() { - return null; - } - @Override - Protocol protocol() { - return null; - } + private static class Wrapper { - @Override - OutboundMessageType messageTemplate() { - return null; - } + T data; - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ - @Override - Bootstrap bootstrap() { - return null; - } - - public TestStep(String marker) { - this.marker = marker; - } - - /** - * On a call to accept, we modify the token to reflect what the current step is, so we can get - * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated - * in order. - */ - @Override - public void accept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - if (!isLastStep) { - nextStep().accept(token); - } else { - ((TestStep)nextStep()).specialAccept(token); - } - } - - /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ - public void specialAccept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - return; + public Wrapper(T data) { + this.data = data; } } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = Mockito.mock(ProbingStep.class); - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(firstStep) @@ -119,16 +59,25 @@ public void testSequenceBasicConstruction_Success() { .addStep(thirdStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(thirdStep); + assertThat(thirdStep.nextStep()).isEqualTo(firstStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); + assertThat(wrapper.data).isTrue(); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = setupMock(); + ProbingStep secondStep = setupMock(); + ProbingStep thirdStep = setupMock(); + + Token testToken = Mockito.mock(Token.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addStep(thirdStep) @@ -137,9 +86,16 @@ public void testSequenceAdvancedConstruction_Success() { .addStep(firstStep) .build(); + assertThat(firstStep.nextStep()).isEqualTo(secondStep); + assertThat(secondStep.nextStep()).isEqualTo(firstStep); + assertThat(thirdStep.nextStep()).isEqualTo(secondStep); + + Wrapper wrapper = new Wrapper<>(false); + doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); + sequence.start(); - assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); + assertThat(wrapper.data).isTrue(); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index da262c52a74..91a113940e8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,17 +11,19 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.blackbox.TestUtils.dummyStep; -import static google.registry.monitoring.blackbox.TestUtils.testStep; -import static google.registry.testing.JUnitBackports.assertThrows; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; import google.registry.monitoring.blackbox.TestUtils.TestProvider; @@ -29,19 +31,20 @@ import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; import javax.inject.Provider; +import org.joda.time.Duration; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; @@ -50,18 +53,18 @@ public class ProbingStepTest { /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final static String ADDRESS_NAME = "TEST_ADDRESS"; + private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final static int PROTOCOL_PORT = 0; + private final static String TEST_MESSAGE = "TEST_MESSAGE"; + private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -72,116 +75,108 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); + /** + * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} + * is called, it just marks the supplied future as succeeded, returning the requisite token. + */ + private ProbingStep dummyStep() { + ProbingStep dummyStep = Mockito.mock(ProbingStep.class); + doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); + doCallRealMethod().when(dummyStep).nextStep(); + return dummyStep; } - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = testStep(testProtocol, TEST_MESSAGE, bootstrap, address); - dummyStep = dummyStep(eventLoopGroup); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - } + @Test + public void testNewChannel() throws Exception { + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() + // Sets up Protocol for when we create a new channel. + Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(false) .build(); - } - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) .build(); - } - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - //there should be no next step - assertThat(firstStep.bootstrap()).isEqualTo(bootstrap); + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); - } - - @Test - public void testNewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + //Set up blackbox server that receives our messages then echoes them back to us + nettyRule.setUpServer(address); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - //Call accept on the first step, which should send our message to the server, which will then be //echoed back to us, causing us to move to the next step firstStep.accept(testToken); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); + nettyRule.assertReceivedMessage(TEST_MESSAGE); //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); + verify(dummyStep, times(1)).accept(any(Token.class)); } + @Ignore @Test public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupChannel(); - setupExistingChannelToken(); + // Wrapper provider classes of handlers. + Provider testHandlerProvider = new TestProvider<>(testHandler); + Provider conversionHandlerProvider = new TestProvider<>( + conversionHandler); + + // Sets up Protocol for when a channel already exists. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) + .build(); + + // Sets up our main step (firstStep) and throwaway step (dummyStep). + ProbingStep firstStep = ProbingStep.builder() + .setBootstrap(bootstrap) + .setDuration(Duration.ZERO) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setProtocol(testProtocol) + .build(); + + //Sets up mock dummy step that returns succeeded promise when we successfully reach it. + ProbingStep dummyStep = dummyStep(); + + firstStep.nextStep(dummyStep); + dummyStep.nextStep(firstStep); + + // Sets up an embedded channel to contain the two handlers we created already. + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + + //Assures that the channel has a succeeded connectionFuture. + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. + Token testToken = new ExistingChannelToken(channel, ""); //checks that the ProbingSteps are appropriately pointing to each other assertThat(firstStep.nextStep()).isEqualTo(dummyStep); @@ -198,17 +193,13 @@ public void testWithSequence_ExistingChannel() throws Exception { //Ensures the accurate message is sent down the pipeline assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - //Write response to our message down EmbeddedChannel pipeline channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); + //At this point, we should have received the message, so the future obtained should be marked + // as a success + verify(dummyStep, times(1)).accept(any(Token.class)); - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index a4474b6b8b5..12e25a6bc6c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -14,24 +14,16 @@ package google.registry.monitoring.blackbox.TestServers; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; - import com.google.common.collect.ImmutableList; import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform @@ -65,35 +57,5 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } - /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. - */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { - - private final CompletableFuture requestFuture = new CompletableFuture<>(); - - public Future getRequestFuture() { - return requestFuture; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } - - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index e7f125bb906..4da75b31c25 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequest; @@ -74,7 +75,7 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr * Handler that will wither redirect client, give successful response, or give error messge */ @Sharable - static class RedirectHandler extends ChannelDuplexHandler { + static class RedirectHandler extends SimpleChannelInboundHandler { private String redirectInput; private String destinationInput; @@ -90,8 +91,7 @@ public RedirectHandler(String redirectInput, String destinationInput) { /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - HttpRequest request = (HttpRequest) msg; + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index e9b74c969f2..2567a7cc155 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,45 +16,24 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; +import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMethod;; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.concurrent.DefaultPromise; -import java.net.Socket; -import java.net.SocketAddress; import javax.inject.Provider; -import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { - static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -79,33 +58,13 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); + response.headers().set("content-type", "text/plain"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } - return response; - } - - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); return response; } @@ -124,100 +83,6 @@ public E get() { } } - /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ - public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { - - String message; - - public DuplexMessageTest() { - message = ""; - } - - public DuplexMessageTest(String msg) { - message = msg; - } - - @Override - public String toString() { - return message; - } - - @Override - public OutboundMessageType modifyMessage(String... args) throws InternalException { - message = args[0]; - return this; - } - - @Override - public String name() { - return "Test Message of: " + this.toString(); - } - } - - /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .setAddress(address) - .build(); - - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); - } - - /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { - private DefaultPromise future; - - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; - } - - @Nullable - @Override - SocketAddress address() { - return null; - } - - @Override - public void accept(Token token) { - future.setSuccess(token); - } - public DefaultPromise getFuture() { - return future; - } - - @Override - public String toString() { - return "Dummy Step"; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; @@ -236,7 +101,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType message) { } @Override - public String getHost() { + public String host() { return host; } @@ -266,21 +131,5 @@ public Channel channel() { return channel; } } - - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java deleted file mode 100644 index 67963805733..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) - */ -@RunWith(JUnit4.class) -public class TokenTest { - - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - - public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); - - @Test - public void testWebToken_MessageModificationSuccess() { - //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); - - //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(InternalException e) { - throw new RuntimeException(e); - } - - - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 196141bb875..c9d337d6ad8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -32,7 +32,7 @@ * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +40,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 1d14cf131e6..86b54d9a07d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -25,14 +25,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.truth.ThrowableSubject; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.TestServer.EchoHandler; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -44,7 +41,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.ReferenceCountUtil; import java.util.concurrent.CompletableFuture; @@ -55,7 +51,7 @@ /** * Helper for setting up and testing client / server connection with netty. * - *

Code based on and almost identical to {@link google.registry.proxy.handler.NettyRule}. + *

Code based on and almost identical to {@code NettyRule} in the proxy. * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

*/ public final class NettyRule extends ExternalResource { @@ -83,10 +79,12 @@ public NettyRule(EventLoopGroup e) { private Channel channel; /** Sets up a server channel bound to the given local address. */ - public void setUpServer(LocalAddress localAddress, ChannelHandler handler) { + public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.of(handler, echoHandler)); + + webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + ImmutableList.builder().add(handlers).add(echoHandler).build()); } /** Sets up a client channel connecting to the give local address. */ @@ -124,7 +122,7 @@ private void checkReady() { } /** Test that custom setup to send message to current server sends right message */ - public void assertThatCustomWorks(String message) throws Exception { + public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); } @@ -165,6 +163,38 @@ ThrowableSubject assertThatClientRootCause() { } + /** + * A handler that echoes back its inbound message. The message is also saved in a promise for + * inspection later. + */ + public static class EchoHandler extends ChannelInboundHandlerAdapter { + + private final CompletableFuture requestFuture = new CompletableFuture<>(); + + public Future getRequestFuture() { + return requestFuture; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // In the test we only send messages of type ByteBuf. + + assertThat(msg).isInstanceOf(ByteBuf.class); + String request = ((ByteBuf) msg).toString(UTF_8); + // After the message is written back to the client, fulfill the promise. + ChannelFuture unusedFuture = + ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); + } + + /** + * Saves any inbound error as the cause of the promise failure. + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ChannelFuture unusedFuture = + ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); + } + } /** A handler that dumps its inbound message to a promise that can be inspected later. */ private static class DumpHandler extends ChannelInboundHandlerAdapter { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 83c8e132f07..523fb228752 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -22,12 +22,7 @@ import static google.registry.monitoring.blackbox.handlers.SslInitializerTestUtils.signKeyPair; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index e170fad8b8c..95b06e623d1 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -25,17 +25,16 @@ */ public class TestActionHandler extends ActionHandler { - private String receivedMessage; + private InboundMessageType receivedMessage; @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws ResponseException, InternalException { - receivedMessage = inboundMessage.toString(); + throws FailureException, UndeterminedStateException { + receivedMessage = inboundMessage; super.channelRead0(ctx, inboundMessage); } - @Override - public String toString() { + public InboundMessageType getResponse() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index e7930f69c7d..3667f3f3d9a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.truth.Truth.assertThat; +import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; @@ -25,14 +26,12 @@ import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; @@ -54,6 +53,7 @@ */ @RunWith(JUnit4.class) public class WebWhoisActionHandlerTest { + private static final int HTTP_PORT = 80; private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; @@ -63,13 +63,12 @@ public class WebWhoisActionHandlerTest { private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); - private static final String ADDRESS_STRING ="TEST_IDENTIFICATION"; - private static final LocalAddress DEFAULT_ADDRESS = new LocalAddress(ADDRESS_STRING); - private static final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of()) - .setName("test_protocol") + private final Protocol STANDARD_PROTOCOL = Protocol.builder() + .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( + null, null, null, null)))) + .setName("http") .setPersistentConnection(false) - .setPort(HTTPS_PORT) + .setPort(HTTP_PORT) .build(); @@ -78,12 +77,13 @@ public class WebWhoisActionHandlerTest { private ActionHandler actionHandler; private ProbingAction probingAction; private Provider actionHandlerProvider; + private Protocol initialProtocol; + private HttpRequestMessage msg; - private void generateLocalAddress() { - address = new LocalAddress(ADDRESS_STRING + System.currentTimeMillis()); - } - /** Creates default protocol with empty list of handlers and specified other inputs */ + /** + * Creates default protocol with empty list of handlers and specified other inputs + */ private Protocol createProtocol(String name, int port, boolean persistentConnection) { return Protocol.builder() .setName(name) @@ -93,27 +93,26 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect .build(); } - /** Initializes new WebWhoisActionHandler */ + /** + * Initializes new WebWhoisActionHandler + */ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, STANDARD_PROTOCOL, STANDARD_PROTOCOL, - messageTemplate, - 80, - 443 + messageTemplate ); actionHandlerProvider = new TestProvider<>(actionHandler); } - /** Sets up testing channel with requisite attributes */ + /** + * Sets up testing channel with requisite attributes + */ private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); - setupProbingActionBasic( - protocol, - outboundMessage, - makeBootstrap(new NioEventLoopGroup(1))); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); } private Bootstrap makeBootstrap(EventLoopGroup group) { @@ -121,230 +120,136 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .group(group) .channel(LocalChannel.class); } - /**Sets up probingAction for when testing redirection */ - private void setupProbingActionBasic(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(TARGET_HOST) - .setAddress(DEFAULT_ADDRESS) - .setChannel(channel) - .build(); - } - private void setupProbingActionAdvanced(Protocol protocol, HttpRequestMessage outboundMessage, Bootstrap bootstrap, String host) { + private void setupProbingActionWithoutChannel(Protocol protocol, + HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { probingAction = ProbingAction.builder() .setProtocol(protocol) .setOutboundMessage(outboundMessage) .setDelay(DEFAULT_DURATION) .setBootstrap(bootstrap) - .setHost(host) - .setAddress(address) + .setHost(addressString) .build(); } - private void setupLocalServer(String redirectInput, String destinationInput, EventLoopGroup group) { + private void setupLocalServer(String redirectInput, String destinationInput, + EventLoopGroup group) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } - @Test - public void testBasic_responseOk() throws Exception { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); + private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { + msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, true); - generateLocalAddress(); + initialProtocol = createProtocol("testProtocol", 0, persistentConnection); + } + @Test + public void testBasic_responseOk() { + //setup + setup("", null, true); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that we successfully received good response and protocol is unchanged assertThat(future.isSuccess()).isTrue(); - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); } @Test - public void testBasic_responseFailure() { + public void testBasic_responseFailure_badRequest() { //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseBad", 0, true); - generateLocalAddress(); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + FullHttpResponse response = new HttpResponseMessage( + makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); //assesses that listener is triggered, but event is not success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); + assertThat(future.isDone()).isTrue(); + assertThat(future.isSuccess()).isFalse(); //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); - } - @Test - public void testBasic_responseError() { - //setup - Bootstrap bootstrap = null; - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseError", 0, true); - generateLocalAddress(); - setupChannel(initialProtocol, msg); - - //stores future - ChannelFuture future = actionHandler.getFinishedFuture(); - channel.writeOutbound(msg); - - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - - //assesses that future listener isn't triggered yet. - assertThat(testPromise.isSuccess()).isFalse(); - - channel.writeInbound(response); - - //assesses that listener is triggered, and event is success - assertThat(testPromise.isSuccess()).isTrue(); - assertThat(future.isSuccess()).isTrue(); - //ensures Protocol is the same - assertThat(channel.attr(PROTOCOL_KEY).get()).isEqualTo(initialProtocol); + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test - public void testBasic_redirectCloseChannel() { + public void testBasic_responseFailure_badURL() { //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest("", "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", 0, true); - generateLocalAddress(); + setup("", null, false); setupChannel(initialProtocol, msg); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - //setup for checker to ensure future listener isn't triggered to early - ChannelPromise testPromise = channel.newPromise(); - future.addListener(f -> testPromise.setSuccess()); - - FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + REDIRECT_HOST, true, false)); + FullHttpResponse response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); - //checks that future has not been set to successful or a failure - assertThat(testPromise.isSuccess()).isFalse(); + //assesses that future listener isn't triggered yet. + assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //makes sure old channel is shut down when attempting redirection - assertThat(channel.isActive()).isFalse(); - + //assesses that listener is triggered, and event is success + assertThat(future.isDone()).isTrue(); + assertThat(future.isSuccess()).isFalse(); + //ensures Protocol is the same + assertThat(future.cause() instanceof FailureException); } @Test - public void testBasic_redirectHost() { - //setup - Bootstrap bootstrap = new Bootstrap() - .group(new NioEventLoopGroup(1)) - .channel(LocalChannel.class); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("redirectHttp", HTTP_PORT, true); - generateLocalAddress(); + public void testAdvanced_redirect() { + // Sets up EventLoopGroup with 1 thread to be blocking. + EventLoopGroup group = new NioEventLoopGroup(1); + + // Sets up embedded channel. + setup("", makeBootstrap(group), false); setupChannel(initialProtocol, msg); - HttpResponse originalResponse = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.FOUND, HTTPS_REDIRECT + REDIRECT_HOST + REDIRECT_PATH, true, false)); + // Initializes LocalAddress with unique String. + String host = TARGET_HOST + System.currentTimeMillis(); + address = new LocalAddress(host); - //store future - ChannelFuture future = actionHandler.getFuture(); + //stores future + ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); + // Sets up the local server that the handler will be redirected to. + setupLocalServer("", host, group); - channel.writeInbound(originalResponse); - - Protocol newProtocol = channel.attr(PROTOCOL_KEY).get(); - + FullHttpResponse response = + new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, + HTTP_REDIRECT + host, true, false)); - //ensures that the new protocol has host and port specified by redirection - assertThat(newProtocol.port()).isEqualTo(HTTPS_PORT); - } - - @Test - public void testAdvanced_responseOk() throws InternalException { - //setup - Bootstrap bootstrap = null; - EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(TARGET_HOST, "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), TARGET_HOST); - - //stores future - ChannelFuture future = probingAction.call(); - - //assesses that we successfully received good response and protocol is unchanged - assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); - } + //checks that future has not been set to successful or a failure + assertThat(future.isDone()).isFalse(); - @Test - public void testAdvanced_responseFailure() throws InternalException { - //setup - Bootstrap bootstrap = null; - EventLoopGroup group = new NioEventLoopGroup(1); - HttpRequestMessage msg = new HttpRequestMessage(makeHttpGetRequest(DUMMY_URL, "")); - setupActionHandler(bootstrap, msg); - Protocol initialProtocol = createProtocol("responseOk", 0, false); - generateLocalAddress(); - setupLocalServer("", TARGET_HOST, group); - setupProbingActionAdvanced(initialProtocol, msg, makeBootstrap(group), DUMMY_URL); + channel.writeInbound(response); - //stores future - ChannelFuture future = probingAction.call(); + //makes sure old channel is shut down when attempting redirection + assertThat(channel.isActive()).isFalse(); //assesses that we successfully received good response and protocol is unchanged assertThat(future.syncUninterruptibly().isSuccess()).isTrue(); } - } - diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index 922c3052bda..c31a9d336bd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,6 +24,10 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; + public TestMessage() { + this(""); + } + public TestMessage(String msg) { message = msg; } From 92e8571c508900dd2ba664abbeb6c96872d46f20 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 16:42:43 -0400 Subject: [PATCH 271/337] Removed TestProvider from TestUtils. --- .../blackbox/ProbingActionTest.java | 7 ++-- .../monitoring/blackbox/ProbingStepTest.java | 11 +++--- .../blackbox/TestServers/TestServer.java | 3 -- .../monitoring/blackbox/TestUtils.java | 17 --------- .../handlers/WebWhoisActionHandlerTest.java | 36 ++++++------------- .../blackbox/messages/TestMessage.java | 4 --- 6 files changed, 18 insertions(+), 60 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index ec5ee5d77ec..f7857dd80f9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -64,8 +63,8 @@ public class ProbingActionTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + private Provider testHandlerProvider = () -> testHandler; + private Provider conversionHandlerProvider = () -> conversionHandler; /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -156,7 +155,7 @@ public void testSuccess_newChannel() throws Exception { future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(testHandler.toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 91a113940e8..1f09dd13553 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -90,9 +89,8 @@ private ProbingStep dummyStep() { @Test public void testNewChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when we create a new channel. Protocol testProtocol = Protocol.builder() @@ -142,9 +140,8 @@ public void testNewChannel() throws Exception { @Test public void testWithSequence_ExistingChannel() throws Exception { // Wrapper provider classes of handlers. - Provider testHandlerProvider = new TestProvider<>(testHandler); - Provider conversionHandlerProvider = new TestProvider<>( - conversionHandler); + Provider testHandlerProvider = () -> testHandler; + Provider conversionHandlerProvider = () -> conversionHandler; // Sets up Protocol for when a channel already exists. Protocol testProtocol = Protocol.builder() diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 12e25a6bc6c..46615a506fb 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -29,15 +29,12 @@ * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform */ public abstract class TestServer { - private LocalAddress localAddress; TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - this.localAddress = localAddress; - //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 2567a7cc155..50c60d9fc52 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -21,7 +21,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -29,7 +28,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Provider; /** Utility class for various helper methods used in testing. */ public class TestUtils { @@ -68,21 +66,6 @@ public static FullHttpResponse makeRedirectResponse( return response; } - /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ - public static class TestProvider implements Provider { - - private E obj; - - public TestProvider(E obj) { - this.obj = obj; - } - - @Override - public E get() { - return obj; - } - } - /** Basic outline for {@link Token} instances to be used in tests */ static abstract class TestToken extends Token { protected String host; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 3667f3f3d9a..33eb190a66a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -25,7 +25,6 @@ import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; @@ -64,18 +63,16 @@ public class WebWhoisActionHandlerTest { private static final String DUMMY_URL = "__WILL_NOT_WORK__"; private static final Duration DEFAULT_DURATION = new Duration(0L); private final Protocol STANDARD_PROTOCOL = Protocol.builder() - .setHandlerProviders(ImmutableList.of(new TestProvider<>(new WebWhoisActionHandler( - null, null, null, null)))) + .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( + null, null, null, null))) .setName("http") .setPersistentConnection(false) .setPort(HTTP_PORT) .build(); - private LocalAddress address; private EmbeddedChannel channel; private ActionHandler actionHandler; - private ProbingAction probingAction; private Provider actionHandlerProvider; private Protocol initialProtocol; private HttpRequestMessage msg; @@ -103,13 +100,13 @@ private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageT STANDARD_PROTOCOL, messageTemplate ); - actionHandlerProvider = new TestProvider<>(actionHandler); + actionHandlerProvider = () -> actionHandler; } /** * Sets up testing channel with requisite attributes */ - private void setupChannel(Protocol protocol, HttpRequestMessage outboundMessage) { + private void setupChannel(Protocol protocol) { channel = new EmbeddedChannel(actionHandler); channel.attr(PROTOCOL_KEY).set(protocol); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); @@ -121,19 +118,8 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } - private void setupProbingActionWithoutChannel(Protocol protocol, - HttpRequestMessage outboundMessage, Bootstrap bootstrap, String addressString) { - probingAction = ProbingAction.builder() - .setProtocol(protocol) - .setOutboundMessage(outboundMessage) - .setDelay(DEFAULT_DURATION) - .setBootstrap(bootstrap) - .setHost(addressString) - .build(); - } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group) { + EventLoopGroup group, LocalAddress address) { WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); } @@ -148,7 +134,7 @@ private void setup(String hostName, Bootstrap bootstrap, boolean persistentConne public void testBasic_responseOk() { //setup setup("", null, true); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -169,7 +155,7 @@ public void testBasic_responseOk() { public void testBasic_responseFailure_badRequest() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -195,7 +181,7 @@ public void testBasic_responseFailure_badRequest() { public void testBasic_responseFailure_badURL() { //setup setup("", null, false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); @@ -224,18 +210,18 @@ public void testAdvanced_redirect() { // Sets up embedded channel. setup("", makeBootstrap(group), false); - setupChannel(initialProtocol, msg); + setupChannel(initialProtocol); // Initializes LocalAddress with unique String. String host = TARGET_HOST + System.currentTimeMillis(); - address = new LocalAddress(host); + LocalAddress address = new LocalAddress(host); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group); + setupLocalServer("", host, group, address); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index c31a9d336bd..922c3052bda 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,10 +24,6 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; - public TestMessage() { - this(""); - } - public TestMessage(String msg) { message = msg; } From e1644ba6a183586df9547acbaebc7b5fef466c51 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 09:46:27 -0400 Subject: [PATCH 272/337] Rebased to master --- .../monitoring/blackbox/handlers/ActionHandler.java | 7 +++++-- .../monitoring/blackbox/TestServers/WebWhoisServer.java | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index 55c9123e3a5..eda82c59a37 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -33,8 +33,11 @@ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, * which informs the {@link ProbingAction} in charge that a response has been read. * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error, lastly, given the type of error, the status of the {@link ResponseType} is marked as a {@code FAILURE} - * or {@code ERROR}. If no exception is thrown and the message reached {@code channelRead0}, then it is marked as {@code SUCCESS}.

+ * of the error. If the error is an instance of a {@link FailureException} {@code finished} is + * marked as a failure with cause {@link FailureException}. If it is any other type of error, it + * is treated as an {@link UndeterminedStateException} and {@code finished} set as a failure with + * the same cause as what caused the exception. Lastly, if no error is thrown, we know the action + * completed as a success, and, as such, we mark {@code finished} as a success.

* *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 4da75b31c25..28b36190a7e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; From be30cbc3d3109e656ce3b6a6ef0c764744450780 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 11:26:33 -0400 Subject: [PATCH 273/337] Updated issues in rebasing --- core/src/main/java/google/registry/ui/package-info.java | 1 - core/src/main/java/google/registry/xjc/package-info.java | 1 - 2 files changed, 2 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..ddff37c6807 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -14,4 +14,3 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.ui; - diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..5b5456585cc 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -14,4 +14,3 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.xjc; - From 4d43c9a4dde009d1f80b4f1d8017ca84ce59c417 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:22:06 -0400 Subject: [PATCH 274/337] Added circular linked list to utils --- .../monitoring/blackbox/WebWhoisModule.java | 8 +- .../blackbox/tokens/WebWhoisToken.java | 32 ++-- .../util/CircularLinkedListIterator.java | 137 ++++++++++++++++++ 3 files changed, 157 insertions(+), 20 deletions(-) create mode 100644 util/src/main/java/google/registry/util/CircularLinkedListIterator.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index de041afad38..e9cf2b69bab 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -23,6 +23,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import google.registry.util.CircularLinkedListIterator; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; @@ -31,6 +32,7 @@ import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.SslProvider; +import java.util.Iterator; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; @@ -194,8 +196,10 @@ int provideMaximumMessageLengthBytes() { @Singleton @Provides @WebWhoisProtocol - ImmutableList provideTopLevelDomains() { - return ImmutableList.of("how", "soy" , "xn--q9jyb4c"); + Iterator provideTopLevelDomains() { + return new CircularLinkedListIterator.Builder() + .addElements("how", "soy" , "xn--q9jyb4c") + .build(); } @Provides diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 2847e5ce0eb..6152fce67d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -16,10 +16,10 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import javax.inject.Inject; import javax.inject.Named; @@ -33,42 +33,38 @@ public class WebWhoisToken extends Token { /** For each top level domain (tld), we probe "prefix.tld". */ - private final String prefix; + private final static String PREFIX = "whois.nic."; /** {@link ImmutableList} of all top level domains to be probed. */ - private final ImmutableList topLevelDomains; + private final Iterator topLevelDomainsIterator; /** Current index of {@code topLevelDomains} that represents tld we are probing. */ - private int domainsIndex; + private String currentDomain; @Inject - public WebWhoisToken( - @Named("Web-WHOIS-Prefix") String prefix, - @WebWhoisProtocol ImmutableList topLevelDomains) { + public WebWhoisToken(@WebWhoisProtocol Iterator topLevelDomainsIterator) { - domainsIndex = 0; - this.prefix = prefix; - this.topLevelDomains = topLevelDomains; + this.topLevelDomainsIterator = topLevelDomainsIterator; + currentDomain = this.topLevelDomainsIterator.next(); } /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ @Override public WebWhoisToken next() { - domainsIndex += 1; - domainsIndex %= topLevelDomains.size(); + currentDomain = topLevelDomainsIterator.next(); return this; } /** Modifies message to reflect the new host coming from the new top level domain. */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws InternalException { - return original.modifyMessage(getHost()); + public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + return original.modifyMessage(host()); } /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ @Override - public String getHost() { - return prefix + topLevelDomains.get(domainsIndex); + public String host() { + return PREFIX + currentDomain; } } diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java new file mode 100644 index 00000000000..710c2f1b74f --- /dev/null +++ b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java @@ -0,0 +1,137 @@ +package google.registry.util; + +import java.util.Iterator; + +/** + * Custom class that support iteration through a circular linked list + * + * @param - Element type stored in the iterator + * + *

Is an immutable object that, when built, creates a circular pointing + * group of Entries, that allows for looped iteration. The first and last + * element in the closed loop are also stored.

+ */ +public class CircularLinkedListIterator implements Iterator { + + /** First {@link Entry} in the circular iterator. */ + private final Entry first; + + /** Last {@link Entry} in the circular iterator. */ + private final Entry last; + + /** Current {@link Entry} in iteration. */ + private Entry current; + + /** Because this is a circular linked list iterator, there is always a next element. */ + @Override + public boolean hasNext() { + return true; + } + + /** Obtains the next element by calling on the {@link Entry}'s next element. */ + @Override + public T next() { + if (current == null) + //If this is first call of next, return first element + current = first; + else + //Otherwise return element after current element + current = current.next; + + return current.data; + } + + /** Returns stored first element. */ + public T getFirst() { + return first.data; + } + + /** Returns stored last element. */ + public T getLast() { + return last.data; + } + + /** + * Node class for {@link CircularLinkedListIterator} that stores value of element + * and points to next {@link Entry}. + * + * @param - Matching element type of iterator. + */ + private static class Entry { + /** Stores the T instance. */ + T data; + + /** Saves reference to next {@link Entry} in iterator. */ + Entry next; + + /** Only needs T instance for initialization. */ + Entry(T data) { + this.data = data; + } + } + + /** + * As {@link CircularLinkedListIterator} is an immutable class, it needs + * a builder for instantiation. + * + * @param - Matching element type of iterator + * + *

Supports adding in element at a time, adding an {@link Iterable} + * of elements, and adding an variable number of elemetns.

+ * + *

Sets first element added to {@code first}, and when built, sets last added + * element to {@code last} and points it to the {@code first} element.

+ */ + public static class Builder { + /** Matching first entry in the circular iterator to be built. */ + private Entry first; + + /** {@link Entry} corresponding to most recent element added. */ + private Entry current; + + /** Sets current {@link Entry} to element added and points previous {@link Entry} to this one. */ + public Builder addElement(T element) { + Entry nextEntry = new Entry<>(element); + if (current == null) + //If this is first element added, we set it to first + first = nextEntry; + else + //Otherwise point previous Entry to this one + current.next = nextEntry; + + current = nextEntry; + return this; + } + + /** Simply calls {@code addElement}, for each element in {@code elements}. */ + public Builder addElements(Iterable elements) { + elements.forEach(this::addElement); + return this; + } + + /** Simply calls {@code addElement}, for each element in {@code elements}. */ + public Builder addElements(T... elements) { + for (T element : elements) + addElement(element); + + return this; + } + + /** Points last {@link Entry} to first {@link Entry}, and calls private constructor. */ + public CircularLinkedListIterator build() { + current.next = first; + return new CircularLinkedListIterator<>(first, current); + } + } + + /** + * After having established pointers between {@link Entry}s, sets + * first element to the first {@link Entry} added to {@link Builder} + * and sets last element to last one added to {@link Builder}. + */ + private CircularLinkedListIterator(Entry first, Entry last) { + this.first = first; + this.last = last; + this.current = first; + } +} From 3f80cb339b8f89c1955c27a7f0b59b9910326ac4 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:24:42 -0400 Subject: [PATCH 275/337] License Header added --- .../monitoring/blackbox/tokens/WebWhoisToken.java | 2 -- .../registry/util/CircularLinkedListIterator.java | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 6152fce67d2..a265d35838d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -19,9 +19,7 @@ import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import java.util.Iterator; -import java.util.LinkedList; import javax.inject.Inject; -import javax.inject.Named; /** * {@link Token} subtype designed for WebWhois sequence. diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java index 710c2f1b74f..3b633a3a2f6 100644 --- a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java +++ b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.util; import java.util.Iterator; From afc60c8226df8bcb0c92396afc8b8e83044ead41 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:18:49 -0400 Subject: [PATCH 276/337] Refactored probing sequence to be circular linked list iterator --- .../monitoring/blackbox/ProbingSequence.java | 147 ++++++++++++------ .../monitoring/blackbox/ProbingStep.java | 90 +---------- .../monitoring/blackbox/WebWhoisModule.java | 10 +- ...> AbstractCircularLinkedListIterator.java} | 62 +++++--- .../DefaultCircularLinkedListIterator.java | 30 ++++ 5 files changed, 180 insertions(+), 159 deletions(-) rename util/src/main/java/google/registry/util/{CircularLinkedListIterator.java => AbstractCircularLinkedListIterator.java} (67%) create mode 100644 util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 2dbf48256f9..6fe0f9ce503 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -14,14 +14,22 @@ package google.registry.monitoring.blackbox; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.util.AbstractCircularLinkedListIterator; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; +import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; /** * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * + *

Inherits from {@link AbstractCircularLinkedListIterator}

, with element type of + * {@link ProbingStep} as the manner in which the sequence is carried out is analogous to + * the {@link AbstractCircularLinkedListIterator} + * * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

@@ -29,65 +37,112 @@ *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

*/ -public class ProbingSequence { - private ProbingStep firstStep; +public class ProbingSequence extends AbstractCircularLinkedListIterator { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); /**Each {@link ProbingSequence} requires a start token to begin running. */ private Token startToken; + /** Starts ProbingSequence by calling first {@code runStep} with {@code startToken}. */ public void start() { - // calls the first step with startToken; - firstStep.accept(startToken); + runStep(startToken); } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * Generates new {@link ProbingAction} from {@link ProbingStep}, calls the action, + * then retrieves the result of the action. + * + * @param token - used to generate the {@link ProbingAction} by calling {@code get().generateAction}. + * + *

Moves on to next {@link ProbingStep} in the iterator and changes the {@link Token} + * to the next one if the previous step was the last one in the loop.

+ * + *

If unable to generate the action, or the calling the action results in an immediate error, + * we note an error. Otherwise, if the future marked as finished when the action is + * completed is marked as a success, we note a success. Otherwise, if the cause of failure + * will either be a failure or error.

*/ - public static class Builder { + private void runStep(Token token) { + Token finalToken; + if (get() == getLast()) + finalToken = token.next(); + else + finalToken = token; + + //Calls next runStep + next(); + + + ProbingAction currentAction; + //attempt to generate new action. On error, move on to next step + try { + currentAction = get().generateAction(finalToken); + } catch(UndeterminedStateException e) { + logger.atWarning().withCause(e).log("Error in Action Generation"); + runStep(finalToken); + return; + } - private ProbingStep currentStep; - private ProbingStep firstStep; - private ProbingStep firstRepeatedStep; - private Bootstrap bootstrap; - private Token startToken; - /** - * Adds {@link Bootstrap} that is supplied to each {@link ProbingStep}. - * - *

Must be called before adding {@link ProbingStep.Builder}s.

- */ - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; - } + ChannelFuture future; + try { + //call the generated action + future = currentAction.call(); + } catch(UndeterminedStateException e) { + //On error in calling action, log error and note an error + logger.atWarning().withCause(e).log("Error in Action Performed"); - /** Adds start token that activate {@link ProbingSequence}. */ - public Builder addToken(Token token) { - startToken = token; - return this; + //Calls next runStep + runStep(finalToken); + return; } - /** - * Adds {@link ProbingStep.Builder}, which is supplied with {@link Bootstrap}, - * built, and pointed to by the previous {@link ProbingStep} added. - */ - public Builder addStep(ProbingStep.Builder stepBuilder) { - assert (bootstrap != null); - ProbingStep step = stepBuilder.setBootstrap(bootstrap).build(); - if (currentStep == null) - firstStep = step; - else - currentStep.nextStep(step); + future.addListener(f -> { + if (f.isSuccess()) { + //On a successful result, we log as a successful step, and not a success + logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - currentStep = step; - return this; + } else { + //On a failed result, we log the failure and note either a failure or error + logger.atSevere().withCause(f.cause()).log("Did not result in future success"); + } + + if (get().protocol().persistentConnection()) + //If the connection is persistent, we store the channel in the token + finalToken.setChannel(currentAction.channel()); + + //Calls next runStep + runStep(finalToken); + + + }); + } + + /** + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with + * supplied {@link Bootstrap}. + */ + public static class Builder extends AbstractCircularLinkedListIterator.Builder { + private Entry firstRepeatedStepEntry; + + private Token startToken; + + /** This Builder must also be supplied with a {@link Token} to construct a {@link ProbingSequence}. */ + public Builder(Token startToken) { + this.startToken = startToken; } /** We take special note of the first repeated step. */ public Builder markFirstRepeated() { - firstRepeatedStep = currentStep; + firstRepeatedStepEntry = current; + return this; + } + + /** Returns this builder as childBuilder. */ + @Override + public Builder childBuilder() { return this; } @@ -95,18 +150,18 @@ public Builder markFirstRepeated() { * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and * calls private constructor to create {@link ProbingSequence}. */ + @Override public ProbingSequence build() { - if (firstRepeatedStep == null) - firstRepeatedStep = firstStep; + if (firstRepeatedStepEntry == null) + firstRepeatedStepEntry = first; - currentStep.nextStep(firstRepeatedStep); - currentStep.lastStep(); - return new ProbingSequence(this.firstStep, this.startToken); + current.setNext(firstRepeatedStepEntry); + return new ProbingSequence(first, current, startToken); } } - private ProbingSequence(ProbingStep firstStep, Token startToken) { - this.firstStep = firstStep; + private ProbingSequence(Entry first, Entry last, Token startToken) { + super(first, last); this.startToken = startToken; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 3df536a9478..bc239726e92 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -15,13 +15,10 @@ package google.registry.monitoring.blackbox; import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelFuture; -import java.util.function.Consumer; import org.joda.time.Duration; /** @@ -35,13 +32,7 @@ * */ @AutoValue -public abstract class ProbingStep implements Consumer { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** Necessary boolean to inform when to obtain next {@link Token}*/ - protected boolean isLastStep = false; - private ProbingStep nextStep; +public abstract class ProbingStep { /** Time delay duration between actions. */ abstract Duration duration(); @@ -73,20 +64,8 @@ public static Builder builder() { return new AutoValue_ProbingStep.Builder(); } - void lastStep() { - isLastStep = true; - } - - void nextStep(ProbingStep step) { - this.nextStep = step; - } - - ProbingStep nextStep() { - return this.nextStep; - } - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ - private ProbingAction generateAction(Token token) throws UndeterminedStateException { + public ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() .setDelay(duration()) @@ -102,70 +81,6 @@ private ProbingAction generateAction(Token token) throws UndeterminedStateExcept return probingActionBuilder.build(); } - - /** On the last step, gets the next {@link Token}. Otherwise, uses the same one. */ - private Token generateNextToken(Token token) { - return (isLastStep) ? token.next() : token; - } - - /** - * Generates new {@link ProbingAction}, calls the action, then retrieves the result of the action. - * - * @param token - used to generate the {@link ProbingAction} by calling {@code generateAction}. - * - *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

- */ - @Override - public void accept(Token token) { - ProbingAction currentAction; - //attempt to generate new action. On error, move on to next step - try { - currentAction = generateAction(token); - } catch(UndeterminedStateException e) { - logger.atWarning().withCause(e).log("Error in Action Generation"); - nextStep.accept(generateNextToken(token)); - return; - } - - - ChannelFuture future; - try { - //call the generated action - future = currentAction.call(); - } catch(Exception e) { - //On error in calling action, log error and note an error - logger.atWarning().withCause(e).log("Error in Action Performed"); - - //Move on to next step in ProbingSequence - nextStep.accept(generateNextToken(token)); - return; - } - - - future.addListener(f -> { - if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success - logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); - - } else { - //On a failed result, we log the failure and note either a failure or error - logger.atSevere().withCause(f.cause()).log("Did not result in future success"); - } - - if (protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token - token.setChannel(currentAction.channel()); - - //Move on the the next step in the ProbingSequence - nextStep.accept(generateNextToken(token)); - - - }); - } - @Override public String toString() { return String.format("ProbingStep with Protocol: %s\n" + @@ -176,4 +91,3 @@ public String toString() { } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index e9cf2b69bab..9b62ec6f774 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -18,12 +18,12 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import google.registry.util.CircularLinkedListIterator; +import google.registry.util.DefaultCircularLinkedListIterator; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; @@ -72,7 +72,7 @@ ProbingSequence provideWebWhoisSequence( WebWhoisToken webWhoisToken) { return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) + .addElement(probingStep) .build(); } @@ -197,7 +197,7 @@ int provideMaximumMessageLengthBytes() { @Provides @WebWhoisProtocol Iterator provideTopLevelDomains() { - return new CircularLinkedListIterator.Builder() + return new DefaultCircularLinkedListIterator.Builder() .addElements("how", "soy" , "xn--q9jyb4c") .build(); } diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java similarity index 67% rename from util/src/main/java/google/registry/util/CircularLinkedListIterator.java rename to util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java index 3b633a3a2f6..9452c053cef 100644 --- a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java +++ b/util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java @@ -14,10 +14,12 @@ package google.registry.util; +import static com.google.common.base.Preconditions.checkNotNull; + import java.util.Iterator; /** - * Custom class that support iteration through a circular linked list + * Immutable class that support circular iteration through a group of elements of type {@param }. * * @param - Element type stored in the iterator * @@ -25,7 +27,7 @@ * group of Entries, that allows for looped iteration. The first and last * element in the closed loop are also stored.

*/ -public class CircularLinkedListIterator implements Iterator { +public abstract class AbstractCircularLinkedListIterator implements Iterator { /** First {@link Entry} in the circular iterator. */ private final Entry first; @@ -33,7 +35,7 @@ public class CircularLinkedListIterator implements Iterator { /** Last {@link Entry} in the circular iterator. */ private final Entry last; - /** Current {@link Entry} in iteration. */ + /** Current {@link Entry} in iterator. */ private Entry current; /** Because this is a circular linked list iterator, there is always a next element. */ @@ -55,6 +57,16 @@ public T next() { return current.data; } + /** Get method for current element in iterator. */ + public T get() { + if (current == null) + //if we have not started iterating, there is no current Entry, so return null + return null; + else + //otherwise, retrieve the current Entry's data + return current.data; + } + /** Returns stored first element. */ public T getFirst() { return first.data; @@ -66,26 +78,31 @@ public T getLast() { } /** - * Node class for {@link CircularLinkedListIterator} that stores value of element + * Node class for {@link AbstractCircularLinkedListIterator} that stores value of element * and points to next {@link Entry}. * * @param - Matching element type of iterator. */ - private static class Entry { - /** Stores the T instance. */ + protected static class Entry { + /** Stores the {@param } instance. */ T data; /** Saves reference to next {@link Entry} in iterator. */ Entry next; - /** Only needs T instance for initialization. */ + /** Necessary for setting next {@link Entry} for subclasses outside of current package. */ + public void setNext(Entry next) { + this.next = next; + } + + /** Only needs {@param } instance for initialization. */ Entry(T data) { this.data = data; } } /** - * As {@link CircularLinkedListIterator} is an immutable class, it needs + * As {@link AbstractCircularLinkedListIterator} is an immutable class, it needs * a builder for instantiation. * * @param - Matching element type of iterator @@ -96,15 +113,15 @@ private static class Entry { *

Sets first element added to {@code first}, and when built, sets last added * element to {@code last} and points it to the {@code first} element.

*/ - public static class Builder { + public abstract static class Builder, L extends AbstractCircularLinkedListIterator> { /** Matching first entry in the circular iterator to be built. */ - private Entry first; + protected Entry first; /** {@link Entry} corresponding to most recent element added. */ - private Entry current; + protected Entry current; /** Sets current {@link Entry} to element added and points previous {@link Entry} to this one. */ - public Builder addElement(T element) { + public Builder addElement(T element) { Entry nextEntry = new Entry<>(element); if (current == null) //If this is first element added, we set it to first @@ -118,24 +135,29 @@ public Builder addElement(T element) { } /** Simply calls {@code addElement}, for each element in {@code elements}. */ - public Builder addElements(Iterable elements) { + public Builder addElements(Iterable elements) { elements.forEach(this::addElement); return this; } /** Simply calls {@code addElement}, for each element in {@code elements}. */ - public Builder addElements(T... elements) { + public Builder addElements(T... elements) { for (T element : elements) addElement(element); return this; } + /** + * Converts {@link Builder} to input subclass. + * + *

Necessary for applying custom build methods when constructing + * subclasses that are inherent to the attributes of those subclasses.

+ */ + public abstract B childBuilder(); + /** Points last {@link Entry} to first {@link Entry}, and calls private constructor. */ - public CircularLinkedListIterator build() { - current.next = first; - return new CircularLinkedListIterator<>(first, current); - } + public abstract L build(); } /** @@ -143,9 +165,9 @@ public CircularLinkedListIterator build() { * first element to the first {@link Entry} added to {@link Builder} * and sets last element to last one added to {@link Builder}. */ - private CircularLinkedListIterator(Entry first, Entry last) { + protected AbstractCircularLinkedListIterator(Entry first, Entry last) { + checkNotNull(last.next); this.first = first; this.last = last; - this.current = first; } } diff --git a/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java b/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java new file mode 100644 index 00000000000..f8356c78a71 --- /dev/null +++ b/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java @@ -0,0 +1,30 @@ +package google.registry.util; + +/** + * Default implementation of {@link AbstractCircularLinkedListIterator} with generic type + * {@param } that operates only in closed circular loop. + * + * @param - Type of elements in iterator. + * + */ +public class DefaultCircularLinkedListIterator extends AbstractCircularLinkedListIterator { + + public static class Builder extends AbstractCircularLinkedListIterator.Builder, DefaultCircularLinkedListIterator> { + + @Override + public Builder childBuilder() { + return this; + } + + /** On build, close loop by pointing last element to first. */ + @Override + public DefaultCircularLinkedListIterator build() { + current.setNext(first); + return new DefaultCircularLinkedListIterator<>(first, current); + } + } + private DefaultCircularLinkedListIterator(Entry first, Entry last) { + super(first, last); + } + +} From 9f2405dda6023285c3d37d3c8fc0a84493f9fc94 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 16:58:05 -0400 Subject: [PATCH 277/337] Modified ProbingStep tests to reflect new ProbingStep structure. --- .../monitoring/blackbox/ProbingSequence.java | 11 +- .../blackbox/ProbingSequenceTest.java | 168 +++++++++++++----- .../monitoring/blackbox/ProbingStepTest.java | 129 ++++---------- .../monitoring/blackbox/TestUtils.java | 6 +- .../blackbox/tokens/WebWhoisTokenTest.java | 20 ++- 5 files changed, 188 insertions(+), 146 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6fe0f9ce503..561d965918e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -53,7 +53,8 @@ public void start() { * Generates new {@link ProbingAction} from {@link ProbingStep}, calls the action, * then retrieves the result of the action. * - * @param token - used to generate the {@link ProbingAction} by calling {@code get().generateAction}. + * @param token - used to generate the {@link ProbingAction} by calling + * {@code get().generateAction}. * *

Moves on to next {@link ProbingStep} in the iterator and changes the {@link Token} * to the next one if the previous step was the last one in the loop.

@@ -63,7 +64,7 @@ public void start() { * completed is marked as a success, we note a success. Otherwise, if the cause of failure * will either be a failure or error.

*/ - private void runStep(Token token) { + void runStep(Token token) { Token finalToken; if (get() == getLast()) finalToken = token.next(); @@ -89,7 +90,7 @@ private void runStep(Token token) { try { //call the generated action future = currentAction.call(); - } catch(UndeterminedStateException e) { + } catch(Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); @@ -124,7 +125,9 @@ private void runStep(Token token) { * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with * supplied {@link Bootstrap}. */ - public static class Builder extends AbstractCircularLinkedListIterator.Builder { + public static class Builder extends AbstractCircularLinkedListIterator.Builder { + private Entry firstRepeatedStepEntry; private Token startToken; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 5c4452df7b3..2777c0de269 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -15,87 +15,171 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.channel.embedded.EmbeddedChannel; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mockito; +/** + * Unit Tests on {@link ProbingSequence} + * + *

First tests the construction of sequences and ensures the ordering is exactly how + * we expect it to be.

+ * + *

Then tests the execution of each step, by ensuring the methods treatment of any kind + * of response from the {@link ProbingStep}s or {@link ProbingAction}s is what is expected.

+ */ @RunWith(JUnit4.class) public class ProbingSequenceTest { + /** Default mock {@link ProbingAction} returned when generating an action with a mockStep. */ + private ProbingAction mockAction; - private ProbingStep setupMock() { - ProbingStep mock = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(mock).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(mock).nextStep(); - return mock; - } + /** + * Default mock {@link ProbingStep} that will usually return a {@code mockAction} on call to + * generate action. + */ + private ProbingStep mockStep; + + /** Default mock {@link Token} that is passed into each {@link ProbingSequence} tested. */ + private Token testToken; + + @Before + public void setup() { + // To avoid a NullPointerException, we must have a protocol return persistent connection as + // false. + Protocol mockProtocol = Mockito.mock(Protocol.class); + doReturn(false).when(mockProtocol).persistentConnection(); - private static class Wrapper { + mockAction = Mockito.mock(ProbingAction.class); - T data; + //In order to avoid a NullPointerException, we must have the protocol returned that stores + // persistent connection as false. + mockStep = Mockito.mock(ProbingStep.class); + doReturn(mockProtocol).when(mockStep).protocol(); - public Wrapper(T data) { - this.data = data; - } + testToken = Mockito.mock(Token.class); } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); - Token testToken = Mockito.mock(Token.class); + ProbingSequence sequence = new ProbingSequence.Builder(testToken) + .addElement(firstStep) + .addElement(secondStep) + .addElement(thirdStep) + .build(); + + assertThat(sequence.next()).isEqualTo(firstStep); + assertThat(sequence.next()).isEqualTo(secondStep); + assertThat(sequence.next()).isEqualTo(thirdStep); + assertThat(sequence.next()).isEqualTo(firstStep); + } + + @Test + public void testSequenceAdvancedConstruction_Success() { + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(firstStep) - .addStep(secondStep) - .addStep(thirdStep) + .addElement(thirdStep) + .addElement(secondStep) + .childBuilder() + .markFirstRepeated() + .addElement(firstStep) .build(); - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(thirdStep); - assertThat(thirdStep.nextStep()).isEqualTo(firstStep); + assertThat(sequence.next()).isEqualTo(thirdStep); + assertThat(sequence.next()).isEqualTo(secondStep); + assertThat(sequence.next()).isEqualTo(firstStep); + assertThat(sequence.next()).isEqualTo(secondStep); + + } + + @Test + public void testRunStep_Success() throws UndeterminedStateException { + // Create channel for the purpose of generating channel futures. + EmbeddedChannel channel = new EmbeddedChannel(); + + //Always returns a succeeded future on call to mockAction. + doReturn(channel.newSucceededFuture()).when(mockAction).call(); + + // Has mockStep always return mockAction on call to generateAction + doReturn(mockAction).when(mockStep).generateAction(any(Token.class)); - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(firstStep).accept(any(Token.class)); + //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + + //Build testable sequence from mocked components. + ProbingSequence sequence = new ProbingSequence.Builder(testToken) + .addElement(mockStep) + .addElement(secondStep) + .build(); sequence.start(); - assertThat(wrapper.data).isTrue(); + assertThat(sequence.get()).isEqualTo(secondStep); } @Test - public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = setupMock(); - ProbingStep secondStep = setupMock(); - ProbingStep thirdStep = setupMock(); + public void testRunStep_FailureRunning() throws UndeterminedStateException { + // Create channel for the purpose of generating channel futures. + EmbeddedChannel channel = new EmbeddedChannel(); + + // Returns a failed future when calling the generated mock action. + doReturn(channel.newFailedFuture(new FailureException(""))).when(mockAction).call(); - Token testToken = Mockito.mock(Token.class); + // Returns mock action on call to generate action for ProbingStep. + doReturn(mockAction).when(mockStep).generateAction(any(Token.class)); + //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + + //Build testable sequence from mocked components. ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addStep(thirdStep) - .addStep(secondStep) - .markFirstRepeated() - .addStep(firstStep) + .addElement(mockStep) + .addElement(secondStep) .build(); - assertThat(firstStep.nextStep()).isEqualTo(secondStep); - assertThat(secondStep.nextStep()).isEqualTo(firstStep); - assertThat(thirdStep.nextStep()).isEqualTo(secondStep); + sequence.start(); - Wrapper wrapper = new Wrapper<>(false); - doAnswer(invocation -> wrapper.data = true).when(thirdStep).accept(any(Token.class)); + assertThat(sequence.get()).isEqualTo(secondStep); + } - sequence.start(); - assertThat(wrapper.data).isTrue(); + @Test + public void testRunStep_FailureGenerating() throws UndeterminedStateException { + // Create a mock first step that returns the dummy action when called to generate an action. + doThrow(UndeterminedStateException.class).when(mockStep).generateAction(any(Token.class)); + + //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + + //Build testable sequence from mocked components. + ProbingSequence sequence = new ProbingSequence.Builder(testToken) + .addElement(mockStep) + .addElement(secondStep) + .build(); + + // When there is an error in action, generating, the next step is immediately called in the same + // thread, so we expect a NullPointerException to be thrown in this thread. + assertThrows(NullPointerException.class, sequence::start); + + assertThat(sequence.get()).isEqualTo(secondStep); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 1f09dd13553..60287d9333f 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; @@ -35,6 +36,7 @@ import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; @@ -43,7 +45,6 @@ import io.netty.channel.nio.NioEventLoopGroup; import javax.inject.Provider; import org.joda.time.Duration; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; @@ -74,129 +75,75 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** - * Sets up Mock dummy step that accurately sets next step and returns it, and when {@code accept} - * is called, it just marks the supplied future as succeeded, returning the requisite token. - */ - private ProbingStep dummyStep() { - ProbingStep dummyStep = Mockito.mock(ProbingStep.class); - doCallRealMethod().when(dummyStep).nextStep(any(ProbingStep.class)); - doCallRealMethod().when(dummyStep).nextStep(); - return dummyStep; - } @Test - public void testNewChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - - // Sets up Protocol for when we create a new channel. + public void testProbingActionGenerate_embeddedChannel() throws UndeterminedStateException { + //setup Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) - .setPersistentConnection(false) + .setPersistentConnection(true) .build(); - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + Token testToken = new ExistingChannelToken(channel, SECONDARY_TEST_MESSAGE); + + ProbingStep testStep = ProbingStep.builder() + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) .setBootstrap(bootstrap) .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) .setProtocol(testProtocol) .build(); - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); + ProbingAction testAction = testStep.generateAction(testToken); - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); + assertThat(testAction.channel()).isEqualTo(channel); + assertThat(testAction.delay()).isEqualTo(Duration.ZERO); + assertThat(testAction.outboundMessage().toString()).isEqualTo(SECONDARY_TEST_MESSAGE); + assertThat(testAction.host()).isEqualTo(SECONDARY_TEST_MESSAGE); + assertThat(testAction.protocol()).isEqualTo(testProtocol); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); - - //Set up blackbox server that receives our messages then echoes them back to us - nettyRule.setUpServer(address); - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //checks that we have appropriately sent the write message to server - nettyRule.assertReceivedMessage(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - verify(dummyStep, times(1)).accept(any(Token.class)); } - @Ignore @Test - public void testWithSequence_ExistingChannel() throws Exception { - // Wrapper provider classes of handlers. - Provider testHandlerProvider = () -> testHandler; - Provider conversionHandlerProvider = () -> conversionHandler; - - // Sets up Protocol for when a channel already exists. + public void testProbingActionGenerate_newChannel() throws UndeterminedStateException { + //setup Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + .setPersistentConnection(false) .build(); - // Sets up our main step (firstStep) and throwaway step (dummyStep). - ProbingStep firstStep = ProbingStep.builder() + nettyRule.setUpServer(address); + + ProbingStep testStep = ProbingStep.builder() + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) .setBootstrap(bootstrap) .setDuration(Duration.ZERO) - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) .setProtocol(testProtocol) .build(); - //Sets up mock dummy step that returns succeeded promise when we successfully reach it. - ProbingStep dummyStep = dummyStep(); - - firstStep.nextStep(dummyStep); - dummyStep.nextStep(firstStep); - - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - - //Assures that the channel has a succeeded connectionFuture. - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, ""); + ProbingAction testAction = testStep.generateAction(testToken); - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + ChannelFuture connectionFuture = testAction.channel().attr(CONNECTION_FUTURE_KEY).get(); + connectionFuture.syncUninterruptibly(); - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); + assertThat(connectionFuture.isSuccess()).isTrue(); + assertThat(testAction.delay()).isEqualTo(Duration.ZERO); + assertThat(testAction.outboundMessage().toString()).isEqualTo(ADDRESS_NAME); + assertThat(testAction.host()).isEqualTo(ADDRESS_NAME); + assertThat(testAction.protocol()).isEqualTo(testProtocol); - Object msg = channel.readOutbound(); - while (msg == null) { - msg = channel.readOutbound(); } - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked - // as a success - verify(dummyStep, times(1)).accept(any(Token.class)); - - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 50c60d9fc52..56a95e1cf59 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,6 +16,7 @@ import static java.nio.charset.StandardCharsets.US_ASCII; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.buffer.ByteBuf; @@ -79,8 +80,9 @@ public Token next() { } @Override - public OutboundMessageType modifyMessage(OutboundMessageType message) { - return message; + public OutboundMessageType modifyMessage(OutboundMessageType message) + throws UndeterminedStateException { + return message.modifyMessage(host); } @Override diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index bf5cfc45652..724411fa1bb 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -21,6 +21,9 @@ import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; +import google.registry.util.AbstractCircularLinkedListIterator; +import google.registry.util.DefaultCircularLinkedListIterator; +import java.util.Iterator; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -36,8 +39,10 @@ public class WebWhoisTokenTest { private static String FIRST_TLD = "first_test"; private static String SECOND_TLD = "second_test"; private static String THIRD_TLD = "third_test"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of(FIRST_TLD, SECOND_TLD, - THIRD_TLD); + private Iterator TEST_DOMAINS = + new DefaultCircularLinkedListIterator.Builder() + .addElements(FIRST_TLD, SECOND_TLD, THIRD_TLD) + .build(); public Token webToken = new WebWhoisToken(TEST_DOMAINS); @@ -49,15 +54,13 @@ public void testMessageModification() throws UndeterminedStateException { //attempts to use Token's method for modifying the method based on its stored host HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX + TEST_DOMAINS.get(0)); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX + FIRST_TLD); } - /** - * As Circular Linked List has not been implemented yet, we cannot yet wrap around, so we don't - * test that in testing {@code next}. - */ @Test public void testNextToken() { + //Simply tests that the next token always has our expected host. + assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD); webToken = webToken.next(); @@ -65,6 +68,9 @@ public void testNextToken() { webToken = webToken.next(); assertThat(webToken.host()).isEqualTo(PREFIX + THIRD_TLD); + webToken = webToken.next(); + + assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD); } } From cd1ee7d8c809c2cd9ec73e25f4baac74663a8719 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 09:57:34 -0400 Subject: [PATCH 278/337] ProbingStepTest modified to have fewer unnecessary helper methods --- .../monitoring/blackbox/ProbingStepTest.java | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 60287d9333f..c6f50eea590 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -16,12 +16,6 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; @@ -34,8 +28,6 @@ import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; @@ -43,11 +35,9 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; -import org.mockito.Mockito; /** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ public class ProbingStepTest { @@ -79,7 +69,7 @@ public class ProbingStepTest { @Test public void testProbingActionGenerate_embeddedChannel() throws UndeterminedStateException { - //setup + // Sets up Protocol to represent existing channel connection. Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) @@ -87,11 +77,15 @@ public void testProbingActionGenerate_embeddedChannel() throws UndeterminedState .setPersistentConnection(true) .build(); + // Sets up an embedded channel to contain the two handlers we created already. EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. Token testToken = new ExistingChannelToken(channel, SECONDARY_TEST_MESSAGE); + // Sets up generic {@link ProbingStep} that we are testing. ProbingStep testStep = ProbingStep.builder() .setMessageTemplate(new TestMessage(TEST_MESSAGE)) .setBootstrap(bootstrap) @@ -99,6 +93,7 @@ public void testProbingActionGenerate_embeddedChannel() throws UndeterminedState .setProtocol(testProtocol) .build(); + ProbingAction testAction = testStep.generateAction(testToken); assertThat(testAction.channel()).isEqualTo(channel); @@ -112,7 +107,7 @@ public void testProbingActionGenerate_embeddedChannel() throws UndeterminedState @Test public void testProbingActionGenerate_newChannel() throws UndeterminedStateException { - //setup + // Sets up Protocol for when we create a new channel. Protocol testProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) @@ -120,8 +115,7 @@ public void testProbingActionGenerate_newChannel() throws UndeterminedStateExcep .setPersistentConnection(false) .build(); - nettyRule.setUpServer(address); - + // Sets up generic ProbingStep that we are testing. ProbingStep testStep = ProbingStep.builder() .setMessageTemplate(new TestMessage(TEST_MESSAGE)) .setBootstrap(bootstrap) @@ -133,6 +127,9 @@ public void testProbingActionGenerate_newChannel() throws UndeterminedStateExcep // channel. Token testToken = new NewChannelToken(ADDRESS_NAME); + // Sets up server listening at LocalAddress so generated action can have successful connection. + nettyRule.setUpServer(address); + ProbingAction testAction = testStep.generateAction(testToken); ChannelFuture connectionFuture = testAction.channel().attr(CONNECTION_FUTURE_KEY).get(); From dcce22ebbd7ed55e7921fdfdd4bc8adde8be1b50 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:22:06 -0400 Subject: [PATCH 279/337] Added circular linked list to utils --- .../monitoring/blackbox/WebWhoisModule.java | 16 +- .../util/CircularLinkedListIterator.java | 137 ++++++++++++++++++ 2 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 util/src/main/java/google/registry/util/CircularLinkedListIterator.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 9b62ec6f774..a83f5f56d0a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,13 +17,16 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; + import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import google.registry.util.DefaultCircularLinkedListIterator; +import google.registry.util.CircularLinkedListIterator; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; @@ -31,8 +34,11 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import java.util.Iterator; +import java.util.List; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; @@ -72,7 +78,7 @@ ProbingSequence provideWebWhoisSequence( WebWhoisToken webWhoisToken) { return new ProbingSequence.Builder(webWhoisToken) - .addElement(probingStep) + .addStep(probingStep) .build(); } @@ -180,10 +186,10 @@ static SslClientInitializer provideSslClientInitializer(SslPro @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClazz){ + Class channelClass){ return new Bootstrap() .group(eventLoopGroup) - .channel(channelClazz); + .channel(channelClass); } @Provides @@ -197,7 +203,7 @@ int provideMaximumMessageLengthBytes() { @Provides @WebWhoisProtocol Iterator provideTopLevelDomains() { - return new DefaultCircularLinkedListIterator.Builder() + return new CircularLinkedListIterator.Builder() .addElements("how", "soy" , "xn--q9jyb4c") .build(); } diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java new file mode 100644 index 00000000000..710c2f1b74f --- /dev/null +++ b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java @@ -0,0 +1,137 @@ +package google.registry.util; + +import java.util.Iterator; + +/** + * Custom class that support iteration through a circular linked list + * + * @param - Element type stored in the iterator + * + *

Is an immutable object that, when built, creates a circular pointing + * group of Entries, that allows for looped iteration. The first and last + * element in the closed loop are also stored.

+ */ +public class CircularLinkedListIterator implements Iterator { + + /** First {@link Entry} in the circular iterator. */ + private final Entry first; + + /** Last {@link Entry} in the circular iterator. */ + private final Entry last; + + /** Current {@link Entry} in iteration. */ + private Entry current; + + /** Because this is a circular linked list iterator, there is always a next element. */ + @Override + public boolean hasNext() { + return true; + } + + /** Obtains the next element by calling on the {@link Entry}'s next element. */ + @Override + public T next() { + if (current == null) + //If this is first call of next, return first element + current = first; + else + //Otherwise return element after current element + current = current.next; + + return current.data; + } + + /** Returns stored first element. */ + public T getFirst() { + return first.data; + } + + /** Returns stored last element. */ + public T getLast() { + return last.data; + } + + /** + * Node class for {@link CircularLinkedListIterator} that stores value of element + * and points to next {@link Entry}. + * + * @param - Matching element type of iterator. + */ + private static class Entry { + /** Stores the T instance. */ + T data; + + /** Saves reference to next {@link Entry} in iterator. */ + Entry next; + + /** Only needs T instance for initialization. */ + Entry(T data) { + this.data = data; + } + } + + /** + * As {@link CircularLinkedListIterator} is an immutable class, it needs + * a builder for instantiation. + * + * @param - Matching element type of iterator + * + *

Supports adding in element at a time, adding an {@link Iterable} + * of elements, and adding an variable number of elemetns.

+ * + *

Sets first element added to {@code first}, and when built, sets last added + * element to {@code last} and points it to the {@code first} element.

+ */ + public static class Builder { + /** Matching first entry in the circular iterator to be built. */ + private Entry first; + + /** {@link Entry} corresponding to most recent element added. */ + private Entry current; + + /** Sets current {@link Entry} to element added and points previous {@link Entry} to this one. */ + public Builder addElement(T element) { + Entry nextEntry = new Entry<>(element); + if (current == null) + //If this is first element added, we set it to first + first = nextEntry; + else + //Otherwise point previous Entry to this one + current.next = nextEntry; + + current = nextEntry; + return this; + } + + /** Simply calls {@code addElement}, for each element in {@code elements}. */ + public Builder addElements(Iterable elements) { + elements.forEach(this::addElement); + return this; + } + + /** Simply calls {@code addElement}, for each element in {@code elements}. */ + public Builder addElements(T... elements) { + for (T element : elements) + addElement(element); + + return this; + } + + /** Points last {@link Entry} to first {@link Entry}, and calls private constructor. */ + public CircularLinkedListIterator build() { + current.next = first; + return new CircularLinkedListIterator<>(first, current); + } + } + + /** + * After having established pointers between {@link Entry}s, sets + * first element to the first {@link Entry} added to {@link Builder} + * and sets last element to last one added to {@link Builder}. + */ + private CircularLinkedListIterator(Entry first, Entry last) { + this.first = first; + this.last = last; + this.current = first; + } +} From 887d5962a02c892784f31ecc51e67c33daf05e41 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:24:42 -0400 Subject: [PATCH 280/337] License Header added --- .../registry/util/CircularLinkedListIterator.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java index 710c2f1b74f..3b633a3a2f6 100644 --- a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java +++ b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.util; import java.util.Iterator; From 53a8d778abb8de58948f8416f1a8d5fca57abb7d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:22:06 -0400 Subject: [PATCH 281/337] Added circular linked list to utils --- .../registry/util/CircularLinkedListIterator.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java index 3b633a3a2f6..710c2f1b74f 100644 --- a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java +++ b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.util; import java.util.Iterator; From 9d882c53017aa3a2813494e76c758abe0a27246b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:24:42 -0400 Subject: [PATCH 282/337] License Header added --- .../registry/util/CircularLinkedListIterator.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java index 710c2f1b74f..3b633a3a2f6 100644 --- a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java +++ b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.util; import java.util.Iterator; From e5fcd0d3ce8cf95c5e666cccf4fba45cec5ac2a0 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:18:49 -0400 Subject: [PATCH 283/337] Refactored probing sequence to be circular linked list iterator --- .../monitoring/blackbox/ProbingSequence.java | 11 +- .../monitoring/blackbox/WebWhoisModule.java | 12 +- .../util/CircularLinkedListIterator.java | 151 ------------------ 3 files changed, 8 insertions(+), 166 deletions(-) delete mode 100644 util/src/main/java/google/registry/util/CircularLinkedListIterator.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 561d965918e..6fe0f9ce503 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -53,8 +53,7 @@ public void start() { * Generates new {@link ProbingAction} from {@link ProbingStep}, calls the action, * then retrieves the result of the action. * - * @param token - used to generate the {@link ProbingAction} by calling - * {@code get().generateAction}. + * @param token - used to generate the {@link ProbingAction} by calling {@code get().generateAction}. * *

Moves on to next {@link ProbingStep} in the iterator and changes the {@link Token} * to the next one if the previous step was the last one in the loop.

@@ -64,7 +63,7 @@ public void start() { * completed is marked as a success, we note a success. Otherwise, if the cause of failure * will either be a failure or error.

*/ - void runStep(Token token) { + private void runStep(Token token) { Token finalToken; if (get() == getLast()) finalToken = token.next(); @@ -90,7 +89,7 @@ void runStep(Token token) { try { //call the generated action future = currentAction.call(); - } catch(Exception e) { + } catch(UndeterminedStateException e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); @@ -125,9 +124,7 @@ void runStep(Token token) { * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with * supplied {@link Bootstrap}. */ - public static class Builder extends AbstractCircularLinkedListIterator.Builder { - + public static class Builder extends AbstractCircularLinkedListIterator.Builder { private Entry firstRepeatedStepEntry; private Token startToken; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index a83f5f56d0a..dac43bef1b9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -20,13 +20,12 @@ import dagger.multibindings.IntoSet; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import google.registry.util.CircularLinkedListIterator; +import google.registry.util.AbstractCircularLinkedListIterator; +import google.registry.util.DefaultCircularLinkedListIterator; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; @@ -34,11 +33,8 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslProvider; import java.util.Iterator; -import java.util.List; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; @@ -78,7 +74,7 @@ ProbingSequence provideWebWhoisSequence( WebWhoisToken webWhoisToken) { return new ProbingSequence.Builder(webWhoisToken) - .addStep(probingStep) + .addElement(probingStep) .build(); } @@ -203,7 +199,7 @@ int provideMaximumMessageLengthBytes() { @Provides @WebWhoisProtocol Iterator provideTopLevelDomains() { - return new CircularLinkedListIterator.Builder() + return new DefaultCircularLinkedListIterator.Builder() .addElements("how", "soy" , "xn--q9jyb4c") .build(); } diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java deleted file mode 100644 index 3b633a3a2f6..00000000000 --- a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2019 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.util; - -import java.util.Iterator; - -/** - * Custom class that support iteration through a circular linked list - * - * @param - Element type stored in the iterator - * - *

Is an immutable object that, when built, creates a circular pointing - * group of Entries, that allows for looped iteration. The first and last - * element in the closed loop are also stored.

- */ -public class CircularLinkedListIterator implements Iterator { - - /** First {@link Entry} in the circular iterator. */ - private final Entry first; - - /** Last {@link Entry} in the circular iterator. */ - private final Entry last; - - /** Current {@link Entry} in iteration. */ - private Entry current; - - /** Because this is a circular linked list iterator, there is always a next element. */ - @Override - public boolean hasNext() { - return true; - } - - /** Obtains the next element by calling on the {@link Entry}'s next element. */ - @Override - public T next() { - if (current == null) - //If this is first call of next, return first element - current = first; - else - //Otherwise return element after current element - current = current.next; - - return current.data; - } - - /** Returns stored first element. */ - public T getFirst() { - return first.data; - } - - /** Returns stored last element. */ - public T getLast() { - return last.data; - } - - /** - * Node class for {@link CircularLinkedListIterator} that stores value of element - * and points to next {@link Entry}. - * - * @param - Matching element type of iterator. - */ - private static class Entry { - /** Stores the T instance. */ - T data; - - /** Saves reference to next {@link Entry} in iterator. */ - Entry next; - - /** Only needs T instance for initialization. */ - Entry(T data) { - this.data = data; - } - } - - /** - * As {@link CircularLinkedListIterator} is an immutable class, it needs - * a builder for instantiation. - * - * @param - Matching element type of iterator - * - *

Supports adding in element at a time, adding an {@link Iterable} - * of elements, and adding an variable number of elemetns.

- * - *

Sets first element added to {@code first}, and when built, sets last added - * element to {@code last} and points it to the {@code first} element.

- */ - public static class Builder { - /** Matching first entry in the circular iterator to be built. */ - private Entry first; - - /** {@link Entry} corresponding to most recent element added. */ - private Entry current; - - /** Sets current {@link Entry} to element added and points previous {@link Entry} to this one. */ - public Builder addElement(T element) { - Entry nextEntry = new Entry<>(element); - if (current == null) - //If this is first element added, we set it to first - first = nextEntry; - else - //Otherwise point previous Entry to this one - current.next = nextEntry; - - current = nextEntry; - return this; - } - - /** Simply calls {@code addElement}, for each element in {@code elements}. */ - public Builder addElements(Iterable elements) { - elements.forEach(this::addElement); - return this; - } - - /** Simply calls {@code addElement}, for each element in {@code elements}. */ - public Builder addElements(T... elements) { - for (T element : elements) - addElement(element); - - return this; - } - - /** Points last {@link Entry} to first {@link Entry}, and calls private constructor. */ - public CircularLinkedListIterator build() { - current.next = first; - return new CircularLinkedListIterator<>(first, current); - } - } - - /** - * After having established pointers between {@link Entry}s, sets - * first element to the first {@link Entry} added to {@link Builder} - * and sets last element to last one added to {@link Builder}. - */ - private CircularLinkedListIterator(Entry first, Entry last) { - this.first = first; - this.last = last; - this.current = first; - } -} From 0f973a6a68f64cf921f200f9f0e57ef000ccac99 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 16:58:05 -0400 Subject: [PATCH 284/337] Modified ProbingStep tests to reflect new ProbingStep structure. --- .../blackbox/ProbingSequenceTest.java | 202 +++++++----------- .../monitoring/blackbox/ProbingStepTest.java | 184 ++++++++++++---- .../monitoring/blackbox/TestUtils.java | 185 +++++++++++++++- .../blackbox/tokens/WebWhoisTokenTest.java | 40 ++-- 4 files changed, 415 insertions(+), 196 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 2777c0de269..62d275c9b2c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -16,66 +16,89 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.testing.JUnitBackports.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.Before; +import io.netty.bootstrap.Bootstrap; +import java.net.SocketAddress; +import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -/** - * Unit Tests on {@link ProbingSequence} - * - *

First tests the construction of sequences and ensures the ordering is exactly how - * we expect it to be.

- * - *

Then tests the execution of each step, by ensuring the methods treatment of any kind - * of response from the {@link ProbingStep}s or {@link ProbingAction}s is what is expected.

- */ + @RunWith(JUnit4.class) public class ProbingSequenceTest { + private final static String TEST_HOST = "TEST_HOST"; + - /** Default mock {@link ProbingAction} returned when generating an action with a mockStep. */ - private ProbingAction mockAction; + private Token testToken = new ProbingSequenceTestToken(); /** - * Default mock {@link ProbingStep} that will usually return a {@code mockAction} on call to - * generate action. + * Custom {@link ProbingStep} subclass that acts as a mock + * step, so we can test how well {@link ProbingSequence} builds + * a linked list of {@link ProbingStep}s from their {@link Builder}s. */ - private ProbingStep mockStep; - - /** Default mock {@link Token} that is passed into each {@link ProbingSequence} tested. */ - private Token testToken; - - @Before - public void setup() { - // To avoid a NullPointerException, we must have a protocol return persistent connection as - // false. - Protocol mockProtocol = Mockito.mock(Protocol.class); - doReturn(false).when(mockProtocol).persistentConnection(); - - mockAction = Mockito.mock(ProbingAction.class); - - //In order to avoid a NullPointerException, we must have the protocol returned that stores - // persistent connection as false. - mockStep = Mockito.mock(ProbingStep.class); - doReturn(mockProtocol).when(mockStep).protocol(); - - testToken = Mockito.mock(Token.class); + private static class TestStep extends ProbingStep { + private String marker; + private DuplexMessageTest message; + + /** We implement all abstract methods to simply return null, as we have no use for them here. */ + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return message; + } + + /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ + @Override + Bootstrap bootstrap() { + return null; + } + + public TestStep(String marker) { + this.marker = marker; + message = new DuplexMessageTest(marker); + } + + /** + * On a call to accept, we modify the token to reflect what the current step is, so we can get + * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated + * in order. + + @Override + public void accept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + if (!isLastStep) { + nextStep().accept(token); + } else { + ((TestStep)nextStep()).specialAccept(token); + } + } + */ + + /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ + public void specialAccept(Token token) { + ((ProbingSequenceTestToken) token).addToHost(marker); + return; + } } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = Mockito.mock(ProbingStep.class); - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + ProbingStep firstStep = new TestStep("first"); + ProbingStep secondStep = new TestStep("second"); + ProbingStep thirdStep = new TestStep("third"); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addElement(firstStep) @@ -83,17 +106,16 @@ public void testSequenceBasicConstruction_Success() { .addElement(thirdStep) .build(); - assertThat(sequence.next()).isEqualTo(firstStep); - assertThat(sequence.next()).isEqualTo(secondStep); - assertThat(sequence.next()).isEqualTo(thirdStep); - assertThat(sequence.next()).isEqualTo(firstStep); + sequence.start(); + + assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = Mockito.mock(ProbingStep.class); - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - ProbingStep thirdStep = Mockito.mock(ProbingStep.class); + ProbingStep firstStep = new TestStep("first"); + ProbingStep secondStep = new TestStep("second"); + ProbingStep thirdStep = new TestStep("third"); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addElement(thirdStep) @@ -103,83 +125,9 @@ public void testSequenceAdvancedConstruction_Success() { .addElement(firstStep) .build(); - assertThat(sequence.next()).isEqualTo(thirdStep); - assertThat(sequence.next()).isEqualTo(secondStep); - assertThat(sequence.next()).isEqualTo(firstStep); - assertThat(sequence.next()).isEqualTo(secondStep); - - } - - @Test - public void testRunStep_Success() throws UndeterminedStateException { - // Create channel for the purpose of generating channel futures. - EmbeddedChannel channel = new EmbeddedChannel(); - - //Always returns a succeeded future on call to mockAction. - doReturn(channel.newSucceededFuture()).when(mockAction).call(); - - // Has mockStep always return mockAction on call to generateAction - doReturn(mockAction).when(mockStep).generateAction(any(Token.class)); - - //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - - //Build testable sequence from mocked components. - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addElement(mockStep) - .addElement(secondStep) - .build(); - sequence.start(); - assertThat(sequence.get()).isEqualTo(secondStep); - } - - @Test - public void testRunStep_FailureRunning() throws UndeterminedStateException { - // Create channel for the purpose of generating channel futures. - EmbeddedChannel channel = new EmbeddedChannel(); - - // Returns a failed future when calling the generated mock action. - doReturn(channel.newFailedFuture(new FailureException(""))).when(mockAction).call(); - - // Returns mock action on call to generate action for ProbingStep. - doReturn(mockAction).when(mockStep).generateAction(any(Token.class)); - - //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - - //Build testable sequence from mocked components. - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addElement(mockStep) - .addElement(secondStep) - .build(); - - sequence.start(); - - assertThat(sequence.get()).isEqualTo(secondStep); - } - - - @Test - public void testRunStep_FailureGenerating() throws UndeterminedStateException { - // Create a mock first step that returns the dummy action when called to generate an action. - doThrow(UndeterminedStateException.class).when(mockStep).generateAction(any(Token.class)); - - //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. - ProbingStep secondStep = Mockito.mock(ProbingStep.class); - - //Build testable sequence from mocked components. - ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addElement(mockStep) - .addElement(secondStep) - .build(); - - // When there is an error in action, generating, the next step is immediately called in the same - // thread, so we expect a NullPointerException to be thrown in this thread. - assertThrows(NullPointerException.class, sequence::start); - - assertThat(sequence.get()).isEqualTo(secondStep); + assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index c6f50eea590..efcd2a026b8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,30 +11,41 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static google.registry.monitoring.blackbox.TestUtils.dummyStep; +import static google.registry.monitoring.blackbox.TestUtils.testStep; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; @@ -43,18 +54,18 @@ public class ProbingStepTest { /** Basic Constants necessary for tests */ - private final static String ADDRESS_NAME = "TEST_ADDRESS"; - private final static String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final static int PROTOCOL_PORT = 0; - private final static String TEST_MESSAGE = "TEST_MESSAGE"; - private final static String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - private final static LocalAddress address = new LocalAddress(ADDRESS_NAME); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); /** Used for testing how well probing step can create connection to blackbox server */ @Rule @@ -65,35 +76,73 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; - @Test - public void testProbingActionGenerate_embeddedChannel() throws UndeterminedStateException { - // Sets up Protocol to represent existing channel connection. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(ADDRESS_NAME); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, SECONDARY_TEST_MESSAGE); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) - .setPersistentConnection(true) + .setPersistentConnection(false) .build(); + } - // Sets up an embedded channel to contain the two handlers we created already. - EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(true) + .build(); + } - // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the - // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, SECONDARY_TEST_MESSAGE); + @Test + public void testProbingActionGenerate_embeddedChannel() throws UndeterminedStateException { + //setup + setupExistingProtocol(); + setupChannel(); + setupExistingChannelToken(); - // Sets up generic {@link ProbingStep} that we are testing. ProbingStep testStep = ProbingStep.builder() - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setMessageTemplate(new DuplexMessageTest(TEST_MESSAGE)) .setBootstrap(bootstrap) .setDuration(Duration.ZERO) .setProtocol(testProtocol) .build(); - ProbingAction testAction = testStep.generateAction(testToken); assertThat(testAction.channel()).isEqualTo(channel); @@ -107,29 +156,18 @@ public void testProbingActionGenerate_embeddedChannel() throws UndeterminedState @Test public void testProbingActionGenerate_newChannel() throws UndeterminedStateException { - // Sets up Protocol for when we create a new channel. - Protocol testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(false) - .build(); + //setup + setupNewProtocol(); + setupNewChannelToken(); + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - // Sets up generic ProbingStep that we are testing. ProbingStep testStep = ProbingStep.builder() - .setMessageTemplate(new TestMessage(TEST_MESSAGE)) + .setMessageTemplate(new DuplexMessageTest(TEST_MESSAGE)) .setBootstrap(bootstrap) .setDuration(Duration.ZERO) .setProtocol(testProtocol) .build(); - // Sets up testToken to return arbitrary values, and no channel. Used when we create a new - // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); - - // Sets up server listening at LocalAddress so generated action can have successful connection. - nettyRule.setUpServer(address); - ProbingAction testAction = testStep.generateAction(testToken); ChannelFuture connectionFuture = testAction.channel().attr(CONNECTION_FUTURE_KEY).get(); @@ -142,5 +180,71 @@ public void testProbingActionGenerate_newChannel() throws UndeterminedStateExcep assertThat(testAction.protocol()).isEqualTo(testProtocol); - } + + + } + + /* + @Test + public void testNewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + } + */ +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index 56a95e1cf59..cd9c5adcf5e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,25 +14,49 @@ package google.registry.monitoring.blackbox; +import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.DefaultPromise; +import java.net.SocketAddress; +import javax.annotation.Nullable; +import javax.inject.Provider; +import org.joda.time.Duration; /** Utility class for various helper methods used in testing. */ public class TestUtils { + static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { + ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); + FullHttpRequest request = + new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); + request + .headers() + .set("user-agent", "Proxy") + .set("host", host) + .setInt("content-length", buf.readableBytes()); + return request; + } + public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -57,18 +81,131 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { public static FullHttpResponse makeRedirectResponse( HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain"); + response.headers().set("content-type", "text/plain").set("content-length", "0"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } + if (hsts) { + response.headers().set("Strict-Transport-Security", "max-age=31536000"); + } return response; } + public static FullHttpRequest makeWhoisHttpRequest( + String content, String host, String path, String accessToken) { + FullHttpRequest request = makeHttpPostRequest(content, host, path); + request + .headers() + .set("authorization", "Bearer " + accessToken) + .set("content-type", "text/plain") + .set("accept", "text/plain"); + return request; + } + + public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { + FullHttpResponse response = makeHttpResponse(content, status); + response.headers().set("content-type", "text/plain"); + return response; + } + + /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ + public static class TestProvider implements Provider { + + private E obj; + + public TestProvider(E obj) { + this.obj = obj; + } + + @Override + public E get() { + return obj; + } + } + + /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ + public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { + + String message; + + public DuplexMessageTest() { + message = ""; + } + + public DuplexMessageTest(String msg) { + message = msg; + } + + @Override + public String toString() { + return message; + } + + @Override + public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { + message = args[0]; + return this; + } + } + + /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ + public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { + return ProbingStep.builder() + .setProtocol(protocol) + .setDuration(Duration.ZERO) + .setMessageTemplate(new DuplexMessageTest(testMessage)) + .setBootstrap(bootstrap) + .build(); + + } + public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { + return new DummyStep(eventLoopGroup); + } + + /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ + public static class DummyStep extends ProbingStep { + private DefaultPromise future; + + public DummyStep(EventLoopGroup eventLoopGroup) { + future = new DefaultPromise(eventLoopGroup.next()) { + }; + } + + @Override + Duration duration() { + return null; + } + + @Override + Protocol protocol() { + return null; + } + + @Override + OutboundMessageType messageTemplate() { + return null; + } + + @Override + Bootstrap bootstrap() { + return null; + } + + public DefaultPromise getFuture() { + return future; + } + + @Override + public String toString() { + return "Dummy Step"; + } + } + /** Basic outline for {@link Token} instances to be used in tests */ - static abstract class TestToken extends Token { + private static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { @@ -116,5 +253,49 @@ public Channel channel() { return channel; } } + + /** {@link TestToken} instance that creates new channel */ + public static class ProbingSequenceTestToken extends TestToken { + public ProbingSequenceTestToken() { + super(""); + } + @Override + public Channel channel() { + return null; + } + + public void addToHost(String suffix) { + host += suffix; + } + + } + + /** + * Compares two {@link FullHttpMessage} for equivalency. + * + *

This method is needed because an HTTP message decoded and aggregated from inbound {@link + * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The + * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even + * though the actual content, headers, etc are the same. + * + *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do + * not use this method directly. + */ + private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { + assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); + assertThat(msg1.headers()).isEqualTo(msg2.headers()); + if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { + assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); + } + } + + public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { + assertThat(res1.status()).isEqualTo(res2.status()); + assertHttpMessageEquivalent(res1, res2); + } + + public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { + assertHttpMessageEquivalent(req1, req2); + } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index 724411fa1bb..847cd052663 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.tokens; +package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; @@ -29,48 +29,34 @@ import org.junit.runners.JUnit4; /** - * Unit Tests for {@link WebWhoisToken} + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) */ @RunWith(JUnit4.class) -public class WebWhoisTokenTest { +public class TokenTest { private static String PREFIX = "whois.nic."; - private static String HOST = "starter"; - private static String FIRST_TLD = "first_test"; - private static String SECOND_TLD = "second_test"; - private static String THIRD_TLD = "third_test"; - private Iterator TEST_DOMAINS = - new DefaultCircularLinkedListIterator.Builder() - .addElements(FIRST_TLD, SECOND_TLD, THIRD_TLD) - .build(); + private static String TEST_STARTER = "starter"; + private static Iterator TEST_DOMAINS = new DefaultCircularLinkedListIterator.Builder().addElement("test").build(); public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test - public void testMessageModification() throws UndeterminedStateException { + public void testWebToken_MessageModificationSuccess() { //creates Request message with header HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", HOST); + message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX + FIRST_TLD); - } - - @Test - public void testNextToken() { - //Simply tests that the next token always has our expected host. + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.next()); + } catch(UndeterminedStateException e) { + throw new RuntimeException(e); + } - assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD); - webToken = webToken.next(); - assertThat(webToken.host()).isEqualTo(PREFIX + SECOND_TLD); - webToken = webToken.next(); - assertThat(webToken.host()).isEqualTo(PREFIX + THIRD_TLD); - webToken = webToken.next(); - assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD); } } From f29bd67d90210b83d82d1054af5d5c59bfe2c04a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 12:50:25 -0400 Subject: [PATCH 285/337] Added missing license header to DefaultCircularLinkedListIterator --- .../util/DefaultCircularLinkedListIterator.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java b/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java index f8356c78a71..367feafde11 100644 --- a/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java +++ b/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.util; /** From 8ac3d02c213a9fab55f3a3dc1db5ca1f6f3a86e8 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 16:30:39 -0400 Subject: [PATCH 286/337] Fixed max column length to be 100 --- .../registry/monitoring/blackbox/Prober.java | 10 +- .../monitoring/blackbox/ProberModule.java | 46 ++-- .../monitoring/blackbox/ProbingAction.java | 182 ++++++++------- .../monitoring/blackbox/ProbingSequence.java | 91 +++++--- .../monitoring/blackbox/ProbingStep.java | 82 ++++--- .../monitoring/blackbox/Protocol.java | 44 ++-- .../monitoring/blackbox/WebWhoisModule.java | 131 +++++++---- .../blackbox/handlers/ActionHandler.java | 54 +++-- .../handlers/SslClientInitializer.java | 11 +- .../handlers/WebWhoisActionHandler.java | 55 +++-- .../handlers/WebWhoisMessageHandler.java | 21 +- .../blackbox/messages/HttpRequestMessage.java | 32 ++- .../messages/HttpResponseMessage.java | 6 +- .../blackbox/messages/InboundMessageType.java | 4 +- .../messages/OutboundMessageType.java | 17 +- .../monitoring/blackbox/tokens/Token.java | 43 ++-- .../blackbox/tokens/WebWhoisToken.java | 34 ++- .../blackbox/ProbingActionTest.java | 25 +- .../blackbox/ProbingSequenceTest.java | 204 +++++++++++------ .../monitoring/blackbox/ProbingStepTest.java | 205 +++++------------ .../blackbox/TestServers/TestServer.java | 15 +- .../blackbox/TestServers/WebWhoisServer.java | 47 ++-- .../monitoring/blackbox/TestUtils.java | 215 ++---------------- .../blackbox/handlers/ConversionHandler.java | 16 +- .../blackbox/handlers/NettyRule.java | 65 +++--- .../handlers/SslClientInitializerTest.java | 42 ++-- .../blackbox/handlers/TestActionHandler.java | 4 +- .../handlers/WebWhoisActionHandlerTest.java | 9 +- .../blackbox/tokens/WebWhoisTokenTest.java | 4 - 29 files changed, 861 insertions(+), 853 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 5ca423c29cc..433d7361d5b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -18,12 +18,16 @@ import google.registry.monitoring.blackbox.ProberModule.ProberComponent; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by + * Dagger. */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + /** + * Main Dagger Component + */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() + .build(); public static void main(String[] args) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java index f9db4865f78..e5a71636173 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProberModule.java @@ -28,44 +28,60 @@ import org.joda.time.Duration; /** - * Dagger main module, which {@link Provides} all objects that are shared between sequences and stores - * {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link ProbingSequence}. + * Dagger main module, which {@link Provides} all objects that are shared between sequences and + * stores {@link ProberComponent}, which allows main {@link Prober} class to obtain each {@link + * ProbingSequence}. */ @Module public class ProberModule { - /** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */ + /** + * Default {@link Duration} chosen to be time between each {@link ProbingAction} call. + */ private static final Duration DEFAULT_DURATION = Duration.standardSeconds(4); - /** {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. */ + /** + * {@link Provides} the {@link SslProvider} used by instances of {@link + * google.registry.monitoring.blackbox.handlers.SslClientInitializer} + */ + @Provides + @Singleton + static SslProvider provideSslProvider() { + // Prefer OpenSSL. + return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; + } + + /** + * {@link Provides} one global {@link EventLoopGroup} shared by each {@link ProbingSequence}. + */ @Provides @Singleton EventLoopGroup provideEventLoopGroup() { return new NioEventLoopGroup(); } - /** {@link Provides} one global {@link Channel} class that is used to construct a {@link io.netty.bootstrap.Bootstrap}. */ + /** + * {@link Provides} one global {@link Channel} class that is used to construct a {@link + * io.netty.bootstrap.Bootstrap}. + */ @Provides @Singleton Class provideChannelClazz() { return NioSocketChannel.class; } - /** {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. */ + + /** + * {@link Provides} above {@code DEFAULT_DURATION} for all provided {@link ProbingStep}s to use. + */ @Provides @Singleton Duration provideDuration() { return DEFAULT_DURATION; } - /** {@link Provides} the {@link SslProvider} used by instances of {@link google.registry.monitoring.blackbox.handlers.SslClientInitializer} */ - @Provides - @Singleton - static SslProvider provideSslProvider() { - // Prefer OpenSSL. - return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; - } - - /** Root level {@link Component} that provides each {@link ProbingSequence}. */ + /** + * Root level {@link Component} that provides each {@link ProbingSequence}. + */ @Singleton @Component( modules = { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 0265390fafe..36413b73452 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -26,75 +26,100 @@ import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; +import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; import javax.inject.Provider; +import org.joda.time.Duration; /** * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the - * task has been completed

+ * to perform its specified task, and return the {@link ChannelFuture} that will be informed when + * the task has been completed

* - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. - * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} - * gives the outline and {@link ProbingAction} gives the details of that connection.

+ *

Is an immutable class, as it is comprised of the tools necessary for making a specific type + * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall + * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the + * details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes + * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when + * informed that the connection is successful. If the channel is supplied, the connection future is + * automatically set to successful.

*/ @AutoValue public abstract class ProbingAction implements Callable { + /** + * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when + * channel is active. + */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey + .valueOf("CONNECTION_FUTURE_KEY"); + /** + * {@link AttributeKey} in channel that gives the information of the channel's host. + */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey + .valueOf("REMOTE_ADDRESS_KEY"); private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** + * {@link Timer} that rate limits probing + */ + private static final Timer timer = new HashedWheelTimer(); - private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; - - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); - - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); + } - /** {@link Timer} that rate limits probing */ - private static final Timer timer = new HashedWheelTimer(); + /** + * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified + * + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified + */ + private static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); + } + } - /** Actual {@link Duration} of this delay */ + /** + * Actual {@link Duration} of this delay + */ public abstract Duration delay(); - /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ + /** + * {@link OutboundMessageType} instance that we write and flush down pipeline to server + */ public abstract OutboundMessageType outboundMessage(); - /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + /** + * {@link Channel} object that either created by or passed into this {@link ProbingAction} + * instance + */ @Nullable public abstract Channel channel(); - /** The {@link Protocol} instance that specifies type of connection */ - public abstract Protocol protocol(); - - /** The hostname of the remote host we have a connection or will make a connection to */ - public abstract String host(); - - /** * Performs the work of the actual action * @@ -112,8 +137,20 @@ public abstract class ProbingAction implements Callable { * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + /** + * The {@link Protocol} instance that specifies type of connection + */ + public abstract Protocol protocol(); + + /** + * The hostname of the remote host we have a connection or will make a connection to + */ + public abstract String host(); - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + /** + * Method that calls on {@code performAction} when it is certain channel connection is + * established. + */ @Override public ChannelFuture call() { //ChannelPromise that we return @@ -134,7 +171,8 @@ public ChannelFuture call() { try { actionHandler = channel().pipeline().get(ActionHandler.class); } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + //If we don't actually have an ActionHandler instance, we have an issue, and throw + // an UndeterminedStateException logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } @@ -142,16 +180,17 @@ public ChannelFuture call() { timer.newTimeout(timeout -> { // Write appropriate outboundMessage to pipeline - channel().writeAndFlush(outboundMessage()); + ChannelFuture unusedflushFuture = channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( future -> { if (future.isSuccess()) { - finished.setSuccess(); + ChannelFuture unusedFuture = finished.setSuccess(); } else { - finished.setFailure(future.cause()); + ChannelFuture unusedFuture = finished.setFailure(future.cause()); } }, - //If we don't have a persistent connection, close the connection to this channel + //If we don't have a persistent connection, close the connection to this + // channel future -> { if (!protocol().persistentConnection()) { @@ -164,7 +203,8 @@ public ChannelFuture call() { } else { logger.atWarning() .log( - "Could not close channel. Stale connection still exists."); + "Could not close channel. Stale connection still exists" + + "."); } } ); @@ -186,10 +226,26 @@ public ChannelFuture call() { return finished; } + @Override + public final String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host() + ); + } - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + /** + * {@link AutoValue.Builder} that does work of creating connection when not already present. + */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; public Builder setBootstrap(Bootstrap bootstrap) { @@ -224,7 +280,8 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); + checkArgument(channel() == null ^ bootstrap == null, + "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel @@ -253,39 +310,4 @@ protected void initChannel(Channel outboundChannel) return autoBuild(); } } - - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); - } - - /** - * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified - * - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified - */ - private static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } - - - - @Override - public String toString() { - return String.format( - "ProbingAction with delay: %d\n" + - "outboundMessage: %s\n" + - "protocol: %s\n" + - "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6fe0f9ce503..6dedc33fae0 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -27,69 +27,80 @@ * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * *

Inherits from {@link AbstractCircularLinkedListIterator}

, with element type of - * {@link ProbingStep} as the manner in which the sequence is carried out is analogous to - * the {@link AbstractCircularLinkedListIterator} + * {@link ProbingStep} as the manner in which the sequence is carried out is analogous to the {@link + * AbstractCircularLinkedListIterator} * * - *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} class type, - * then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one is the first repeated step.

+ *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} + * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one + * is the first repeated step.

* - *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once the first one - * is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest of the work.

+ *

{@link ProbingSequence} implicitly points each {@link ProbingStep} to the next one, so once + * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest + * of the work.

*/ public class ProbingSequence extends AbstractCircularLinkedListIterator { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /**Each {@link ProbingSequence} requires a start token to begin running. */ + /** + * Each {@link ProbingSequence} requires a start token to begin running. + */ private Token startToken; - /** Starts ProbingSequence by calling first {@code runStep} with {@code startToken}. */ + private ProbingSequence(Entry first, Entry last, Token startToken) { + super(first, last); + this.startToken = startToken; + } + + /** + * Starts ProbingSequence by calling first {@code runStep} with {@code startToken}. + */ public void start() { runStep(startToken); } /** - * Generates new {@link ProbingAction} from {@link ProbingStep}, calls the action, - * then retrieves the result of the action. + * Generates new {@link ProbingAction} from {@link ProbingStep}, calls the action, then retrieves + * the result of the action. * - * @param token - used to generate the {@link ProbingAction} by calling {@code get().generateAction}. + * @param token - used to generate the {@link ProbingAction} by calling {@code + * get().generateAction}. * *

Moves on to next {@link ProbingStep} in the iterator and changes the {@link Token} * to the next one if the previous step was the last one in the loop.

* *

If unable to generate the action, or the calling the action results in an immediate error, - * we note an error. Otherwise, if the future marked as finished when the action is - * completed is marked as a success, we note a success. Otherwise, if the cause of failure - * will either be a failure or error.

+ * we note an error. Otherwise, if the future marked as finished when the action is completed is + * marked as a success, we note a success. Otherwise, if the cause of failure will either be a + * failure or error.

*/ private void runStep(Token token) { Token finalToken; - if (get() == getLast()) + if (get() == getLast()) { finalToken = token.next(); - else + } else { finalToken = token; + } //Calls next runStep next(); - ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { currentAction = get().generateAction(finalToken); - } catch(UndeterminedStateException e) { + } catch (UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); runStep(finalToken); return; } - ChannelFuture future; try { //call the generated action future = currentAction.call(); - } catch(UndeterminedStateException e) { + } catch (Exception e) { //On error in calling action, log error and note an error logger.atWarning().withCause(e).log("Error in Action Performed"); @@ -98,7 +109,6 @@ private void runStep(Token token) { return; } - future.addListener(f -> { if (f.isSuccess()) { //On a successful result, we log as a successful step, and not a success @@ -109,9 +119,11 @@ private void runStep(Token token) { logger.atSevere().withCause(f.cause()).log("Did not result in future success"); } - if (get().protocol().persistentConnection()) - //If the connection is persistent, we store the channel in the token + if (get().protocol().persistentConnection()) { + //If the connection is persistent, we store the channel in the token + finalToken.setChannel(currentAction.channel()); + } //Calls next runStep runStep(finalToken); @@ -121,48 +133,53 @@ private void runStep(Token token) { } /** - * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with - * supplied {@link Bootstrap}. + * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link + * Bootstrap}. */ - public static class Builder extends AbstractCircularLinkedListIterator.Builder { + public static class Builder extends AbstractCircularLinkedListIterator.Builder { + private Entry firstRepeatedStepEntry; private Token startToken; - /** This Builder must also be supplied with a {@link Token} to construct a {@link ProbingSequence}. */ + /** + * This Builder must also be supplied with a {@link Token} to construct a {@link + * ProbingSequence}. + */ public Builder(Token startToken) { this.startToken = startToken; } - /** We take special note of the first repeated step. */ + /** + * We take special note of the first repeated step. + */ public Builder markFirstRepeated() { firstRepeatedStepEntry = current; return this; } - /** Returns this builder as childBuilder. */ + /** + * Returns this builder as childBuilder. + */ @Override public Builder childBuilder() { return this; } /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and - * calls private constructor to create {@link ProbingSequence}. + * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private + * constructor to create {@link ProbingSequence}. */ @Override public ProbingSequence build() { - if (firstRepeatedStepEntry == null) + if (firstRepeatedStepEntry == null) { firstRepeatedStepEntry = first; + } current.setNext(firstRepeatedStepEntry); return new ProbingSequence(first, current, startToken); } } - - private ProbingSequence(Entry first, Entry last, Token startToken) { - super(first, last); - this.startToken = startToken; - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index bc239726e92..58414c1524c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -16,55 +16,51 @@ import com.google.auto.value.AutoValue; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.tokens.Token; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; import org.joda.time.Duration; /** - * {@link AutoValue} class that represents generator of actions performed at each step - * in {@link ProbingSequence}. + * {@link AutoValue} class that represents generator of actions performed at each step in {@link + * ProbingSequence}. * *

Holds the unchanged components in a given step of the {@link ProbingSequence}, which are - * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} instances. - * It then modifies these components on each loop iteration with the consumed {@link Token} and from that, - * generates a new {@link ProbingAction} to call.

- * + * the {@link OutboundMessageType}, {@link Protocol}, {@link Duration}, and {@link Bootstrap} + * instances. It then modifies these components on each loop iteration with the consumed {@link + * Token} and from that, generates a new {@link ProbingAction} to call.

*/ @AutoValue public abstract class ProbingStep { - /** Time delay duration between actions. */ + public static Builder builder() { + return new AutoValue_ProbingStep.Builder(); + } + + /** + * Time delay duration between actions. + */ abstract Duration duration(); - /** {@link Protocol} type for this step. */ + /** + * {@link Protocol} type for this step. + */ abstract Protocol protocol(); - /** {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. */ + /** + * {@link OutboundMessageType} instance that serves as template to be modified by {@link Token}. + */ abstract OutboundMessageType messageTemplate(); - /** {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation of new channels. */ + /** + * {@link Bootstrap} instance provided by parent {@link ProbingSequence} that allows for creation + * of new channels. + */ abstract Bootstrap bootstrap(); - - @AutoValue.Builder - public static abstract class Builder { - public abstract Builder setDuration(Duration value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setMessageTemplate(OutboundMessageType value); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract ProbingStep build(); - } - - public static Builder builder() { - return new AutoValue_ProbingStep.Builder(); - } - - /** Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} */ + /** + * Generates a new {@link ProbingAction} from {@code token} modified {@link OutboundMessageType} + */ public ProbingAction generateAction(Token token) throws UndeterminedStateException { OutboundMessageType message = token.modifyMessage(messageTemplate()); ProbingAction.Builder probingActionBuilder = ProbingAction.builder() @@ -73,21 +69,37 @@ public ProbingAction generateAction(Token token) throws UndeterminedStateExcepti .setOutboundMessage(message) .setHost(token.host()); - if (token.channel() != null) + if (token.channel() != null) { probingActionBuilder.setChannel(token.channel()); - else + } else { probingActionBuilder.setBootstrap(bootstrap()); + } return probingActionBuilder.build(); } @Override - public String toString() { - return String.format("ProbingStep with Protocol: %s\n" + - "OutboundMessage: %s\n", + public final String toString() { + return String.format("ProbingStep with Protocol: %s\n" + + "OutboundMessage: %s\n", protocol(), messageTemplate().getClass().getName()); } + /** Standard {@link AutoValue.Builder} for {@link ProbingStep}. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDuration(Duration value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setMessageTemplate(OutboundMessageType value); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract ProbingStep build(); + } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 88b4c7aa6f6..ae7b3ec0f79 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -26,23 +26,41 @@ @AutoValue public abstract class Protocol { - /** {@link AttributeKey} that lets channel reference {@link Protocol} that created it. */ + /** + * {@link AttributeKey} that lets channel reference {@link Protocol} that created it. + */ public static final AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL_KEY"); - abstract String name(); + public static Builder builder() { + return new AutoValue_Protocol.Builder(); + } + + public abstract String name(); public abstract int port(); - /** The {@link ChannelHandler} providers to use for the protocol, in order. */ + /** + * The {@link ChannelHandler} providers to use for the protocol, in order. + */ abstract ImmutableList> handlerProviders(); - /** Boolean that notes if connection associated with Protocol is persistent.*/ + /** + * Boolean that notes if connection associated with Protocol is persistent. + */ abstract boolean persistentConnection(); - public static Builder builder() { - return new AutoValue_Protocol.Builder(); + @Override + public final String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); } + /** Standard {@link AutoValue.Builder} for {@link Protocol}. */ @AutoValue.Builder public static abstract class Builder { @@ -50,21 +68,11 @@ public static abstract class Builder { public abstract Builder setPort(int num); - public abstract Builder setHandlerProviders(ImmutableList> providers); + public abstract Builder setHandlerProviders( + ImmutableList> providers); public abstract Builder setPersistentConnection(boolean value); public abstract Protocol build(); } - - @Override - public String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index dac43bef1b9..9aa864cc019 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -17,14 +17,12 @@ import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; - import dagger.multibindings.IntoSet; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.handlers.SslClientInitializer; import google.registry.monitoring.blackbox.handlers.WebWhoisActionHandler; +import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import google.registry.util.AbstractCircularLinkedListIterator; import google.registry.util.DefaultCircularLinkedListIterator; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -40,46 +38,24 @@ import javax.inject.Singleton; import org.joda.time.Duration; -/** A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. */ +/** + * A module that provides the {@link Protocol}s to send HTTP(S) web WHOIS requests. + */ @Module public class WebWhoisModule { - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; private static final String HTTP_PROTOCOL_NAME = "http"; private static final String HTTPS_PROTOCOL_NAME = "https"; - - /** Standard length of messages used by Proxy. Equates to 0.5 MB. */ + /** + * Standard length of messages used by Proxy. Equates to 0.5 MB. + */ private static final int maximumMessageLengthBytes = 512 * 1024; + private final int HTTP_WHOIS_PORT = 80; + private final int HTTPS_WHOIS_PORT = 443; - - /** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */ - @Qualifier - public @interface HttpWhoisProtocol {} - - /** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */ - @Qualifier - public @interface HttpsWhoisProtocol {} - - /** Dagger qualifier to provide any WebWhois related bindings. */ - @Qualifier - public @interface WebWhoisProtocol {} - - /** {@link Provides} standard WebWhois sequence. */ - @Provides - @Singleton - @IntoSet - ProbingSequence provideWebWhoisSequence( - @WebWhoisProtocol ProbingStep probingStep, - WebWhoisToken webWhoisToken) { - - return new ProbingSequence.Builder(webWhoisToken) - .addElement(probingStep) - .build(); - } - - - /** {@link Provides} only step used in WebWhois sequence. */ + /** + * {@link Provides} only step used in WebWhois sequence. + */ @Provides @WebWhoisProtocol static ProbingStep provideWebWhoisStep( @@ -96,7 +72,9 @@ static ProbingStep provideWebWhoisStep( .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to http connection. */ + /** + * {@link Provides} the {@link Protocol} that corresponds to http connection. + */ @Singleton @Provides @HttpWhoisProtocol @@ -111,7 +89,9 @@ static Protocol provideHttpWhoisProtocol( .build(); } - /** {@link Provides} the {@link Protocol} that corresponds to https connection. */ + /** + * {@link Provides} the {@link Protocol} that corresponds to https connection. + */ @Singleton @Provides @HttpsWhoisProtocol @@ -126,8 +106,10 @@ static Protocol provideHttpsWhoisProtocol( .build(); } - - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http protocol. */ + /** + * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http + * protocol. + */ @Provides @HttpWhoisProtocol static ImmutableList> providerHttpWhoisHandlerProviders( @@ -142,11 +124,15 @@ static ImmutableList> providerHttpWhoisHandle webWhoisActionHandlerProvider); } - /** {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https protocol. */ + /** + * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https + * protocol. + */ @Provides @HttpsWhoisProtocol static ImmutableList> providerHttpsWhoisHandlerProviders( - @HttpsWhoisProtocol Provider> sslClientInitializerProvider, + @HttpsWhoisProtocol + Provider> sslClientInitializerProvider, Provider httpClientCodecProvider, Provider httpObjectAggregatorProvider, Provider messageHandlerProvider, @@ -169,23 +155,43 @@ static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int ma return new HttpObjectAggregator(maxContentLength); } - /** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */ + /** + * {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. + */ @Provides @HttpsWhoisProtocol - static SslClientInitializer provideSslClientInitializer(SslProvider sslProvider) { + static SslClientInitializer provideSslClientInitializer( + SslProvider sslProvider) { return new SslClientInitializer<>(sslProvider); } - /** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */ + /** + * {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. + */ @Singleton @Provides @WebWhoisProtocol static Bootstrap provideBootstrap( EventLoopGroup eventLoopGroup, - Class channelClass){ + Class channelClazz) { return new Bootstrap() .group(eventLoopGroup) - .channel(channelClass); + .channel(channelClazz); + } + + /** + * {@link Provides} standard WebWhois sequence. + */ + @Provides + @Singleton + @IntoSet + ProbingSequence provideWebWhoisSequence( + @WebWhoisProtocol ProbingStep probingStep, + WebWhoisToken webWhoisToken) { + + return new ProbingSequence.Builder(webWhoisToken) + .addElement(probingStep) + .build(); } @Provides @@ -194,13 +200,15 @@ int provideMaximumMessageLengthBytes() { return maximumMessageLengthBytes; } - /** {@link Provides} the list of top level domains to be probed */ + /** + * {@link Provides} the list of top level domains to be probed + */ @Singleton @Provides @WebWhoisProtocol Iterator provideTopLevelDomains() { return new DefaultCircularLinkedListIterator.Builder() - .addElements("how", "soy" , "xn--q9jyb4c") + .addElements("how", "soy", "xn--q9jyb4c") .build(); } @@ -216,5 +224,28 @@ int provideHttpsWhoisPort() { return HTTPS_WHOIS_PORT; } + /** + * Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. + */ + @Qualifier + public @interface HttpWhoisProtocol { + + } + + /** + * Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. + */ + @Qualifier + public @interface HttpsWhoisProtocol { + } + + /** + * Dagger qualifier to provide any WebWhois related bindings. + */ + @Qualifier + public @interface WebWhoisProtocol { + + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java index eda82c59a37..1e1a834231c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ActionHandler.java @@ -16,28 +16,30 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; /** - *Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline + * Superclass of all {@link io.netty.channel.ChannelHandler}s placed at end of channel pipeline * - *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in - * messages that implement the {@link InboundMessageType} interface.

+ *

{@link ActionHandler} inherits from {@link SimpleChannelInboundHandler}, + * as it should only be passed in messages that implement the {@link InboundMessageType} + * interface.

* - *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise}, - * which informs the {@link ProbingAction} in charge that a response has been read. - * Second, with any exception thrown, the connection is closed, and the ProbingAction governing this channel is informed - * of the error. If the error is an instance of a {@link FailureException} {@code finished} is - * marked as a failure with cause {@link FailureException}. If it is any other type of error, it - * is treated as an {@link UndeterminedStateException} and {@code finished} set as a failure with - * the same cause as what caused the exception. Lastly, if no error is thrown, we know the action - * completed as a success, and, as such, we mark {@code finished} as a success.

+ *

The {@link ActionHandler} skeleton exists for a few main purposes. First, it returns a + * {@link ChannelPromise}, which informs the {@link ProbingAction} in charge that a response has + * been read. Second, with any exception thrown, the connection is closed, and the ProbingAction + * governing this channel is informed of the error. If the error is an instance of a {@link + * FailureException} {@code finished} is marked as a failure with cause {@link FailureException}. If + * it is any other type of error, it is treated as an {@link UndeterminedStateException} and {@code + * finished} set as a failure with the same cause as what caused the exception. Lastly, if no error + * is thrown, we know the action completed as a success, and, as such, we mark {@code finished} as a + * success.

* *

Subclasses specify further work to be done for specific kinds of channel pipelines.

*/ @@ -45,32 +47,40 @@ public abstract class ActionHandler extends SimpleChannelInboundHandler privateKeySupplier, Supplier certificateSupplier) { + public SslClientInitializer(SslProvider sslProvider, Supplier privateKeySupplier, + Supplier certificateSupplier) { //We use the default trust store here as well, setting trustCertificates to null this(sslProvider, null, privateKeySupplier, certificateSupplier); } @@ -99,8 +98,10 @@ protected void initChannel(C channel) throws Exception { SslContextBuilder.forClient() .sslProvider(sslProvider) .trustManager(trustedCertificates); - if (privateKeySupplier != null && certificateSupplier != null) - sslContextBuilder = sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get()); + if (privateKeySupplier != null && certificateSupplier != null) { + sslContextBuilder = sslContextBuilder + .keyManager(privateKeySupplier.get(), certificateSupplier.get()); + } SslHandler sslHandler = sslContextBuilder .build() diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 34eac2a0118..c0f7ce8ae78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,17 +14,15 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; @@ -38,10 +36,11 @@ import org.joda.time.Duration; /** - *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection - * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

+ *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response + * implies a redirection it follows the redirection until either an Error Response is received, or + * {@link HttpResponseStatus.OK} is received

*/ public class WebWhoisActionHandler extends ActionHandler { @@ -49,16 +48,24 @@ public class WebWhoisActionHandler extends ActionHandler { /** Dagger injected components necessary for redirect responses: */ - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + /** + * {@link Bootstrap} necessary for remaking connection on redirect response. + */ private final Bootstrap bootstrap; - /** {@link Protocol} for when redirected to http endpoint. */ + /** + * {@link Protocol} for when redirected to http endpoint. + */ private final Protocol httpWhoisProtocol; - /** {@link Protocol} for when redirected to https endpoint. */ + /** + * {@link Protocol} for when redirected to https endpoint. + */ private final Protocol httpsWhoisProtocol; - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + /** + * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. + */ private final HttpRequestMessage requestMessage; @Inject @@ -76,9 +83,10 @@ public WebWhoisActionHandler( /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, + * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a + * response indicating a Failure, or receives a redirection response, where it follows the + * redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) @@ -86,7 +94,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { + if (response.status().equals(HttpResponseStatus.OK)) { logger.atInfo().log("Received Successful HttpResponseStatus"); logger.atInfo().log("Response Received: " + response); @@ -101,13 +109,17 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException( + "Redirected Location was invalid. Given Location was: " + response.headers() + .get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, url.getDefaultPort(), newPath)); + logger.atInfo().log(String + .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, + url.getDefaultPort(), newPath)); //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; @@ -116,7 +128,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new FailureException("Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); + throw new FailureException( + "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -141,10 +154,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atWarning().log("Channel was unsuccessfully closed."); } - //Once channel is closed, establish new connection to redirected host, and repeat same actions + //Once channel is closed, establish new connection to redirected host, and repeat + // same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + //Once we have a successful call, set original ChannelPromise as success to tell + // ProbingStep we can move on secondFuture.addListener(f2 -> { if (f2.isSuccess()) { super.channelRead0(ctx, msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java index 58c395ad86e..576d6a04d42 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisMessageHandler.java @@ -24,25 +24,32 @@ import javax.inject.Inject; /** - * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} - * to custom type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} - * in case of reuse for redirection. + * {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom + * type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for + * redirection. */ public class WebWhoisMessageHandler extends ChannelDuplexHandler { @Inject - public WebWhoisMessageHandler() {} + public WebWhoisMessageHandler() { + } - /** Retains {@link HttpRequestMessage} and calls super write method. */ + /** + * Retains {@link HttpRequestMessage} and calls super write method. + */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) + throws Exception { HttpRequestMessage request = (HttpRequestMessage) msg; request.retain(); super.write(ctx, request, promise); } - /** Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link InboundMessageType} instance. */ + /** + * Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link + * InboundMessageType} instance. + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse originalResponse = (FullHttpResponse) msg; diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 5e9300d0f34..57b4bc2f575 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,14 +19,15 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import java.util.Arrays; import javax.inject.Inject; /** * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. * *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

+ * that modifies the request to reflect the new host and optional path. We also implement a {@code + * name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { @@ -38,30 +39,37 @@ public HttpRequestMessage() { private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, + ByteBuf content) { super(httpVersion, method, uri, content); } + /** + * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} + */ + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } - - /** Modifies headers to reflect new host and new path if applicable. */ + /** + * Modifies headers to reflect new host and new path if applicable. + */ @Override public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { if (args.length == 1 || args.length == 2) { headers().set("host", args[0]); - if (args.length == 2) + if (args.length == 2) { setUri(args[1]); + } return this; @@ -69,7 +77,7 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx throw new IllegalArgumentException( String.format( "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + args, args.length)); + + " Received %d arguments instead of: " + Arrays.toString(args), args.length)); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..c3f173729e9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -33,8 +33,10 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { + /** + * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} + */ + public HttpResponseMessage(FullHttpResponse response) { this(response.protocolVersion(), response.status(), response.content()); response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 578526933ba..1d686e4ec34 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -17,4 +17,6 @@ /** * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline */ -public interface InboundMessageType {} +public interface InboundMessageType { + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index be6c872cc3e..e435ae59f86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -14,16 +14,23 @@ package google.registry.monitoring.blackbox.messages; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline */ public interface OutboundMessageType { - /** All {@link OutboundMessageType} implementing classes should be able to be modified by token with String arguments */ - public OutboundMessageType modifyMessage(String... args) throws InternalException; + /** + * All {@link OutboundMessageType} implementing classes should be able to be modified by token + * with String arguments + */ + OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException; - /** Necessary to inform metrics collector what kind of message is sent down {@link io.netty.channel.ChannelPipeline} */ - public String name(); + /** + * Necessary to inform metrics collector what kind of message is sent down {@link + * io.netty.channel.ChannelPipeline} + */ + @Override + String toString(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java index dd1882b5686..b10c45dae8a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/Token.java @@ -14,41 +14,58 @@ package google.registry.monitoring.blackbox.tokens; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.ProbingSequence; +import google.registry.monitoring.blackbox.ProbingStep; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.channel.Channel; /** - * Superclass that represents information passed to each {@link google.registry.monitoring.blackbox.ProbingStep} - * in a single loop of a {@link google.registry.monitoring.blackbox.ProbingSequence}. + * Superclass that represents information passed to each {@link ProbingStep} in a single loop of a + * {@link ProbingSequence}. * *

Modifies the message passed in to reflect information relevant to a single loop - * in a {@link google.registry.monitoring.blackbox.ProbingSequence}. Additionally, passes - * on channel that remains unchanged within a loop of the sequence.

+ * in a {@link ProbingSequence}. Additionally, passes on channel that remains unchanged within a + * loop of the sequence.

* *

Also obtains the next {@link Token} corresponding to the next iteration of a loop * in the sequence.

*/ public abstract class Token { - /** {@link Channel} that always starts out as null. */ + /** + * {@link Channel} that always starts out as null. Once a persistent connection is made (such as + * EPP), that channel is stored in the token and passed on to later steps in the sequence until a + * new loop begins. + */ protected Channel channel; - /** Obtains next {@link Token} for next loop in sequence. */ + /** + * Obtains next {@link Token} for next loop in sequence. + */ public abstract Token next(); - /** String corresponding to host that is relevant for loop in sequence. */ - public abstract String getHost(); + /** + * String corresponding to host that is relevant for loop in sequence. + */ + public abstract String host(); - /** Modifies the {@link OutboundMessageType} in the manner necessary for each loop */ - public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) throws InternalException; + /** + * Modifies the {@link OutboundMessageType} in the manner necessary for each loop + */ + public abstract OutboundMessageType modifyMessage(OutboundMessageType messageType) + throws UndeterminedStateException; - /** Set method for {@code channel} */ + /** + * Set method for {@code channel} + */ public void setChannel(Channel channel) { this.channel = channel; } - /** Get method for {@code channel}. */ + /** + * Get method for {@code channel}. + */ public Channel channel() { return this.channel; } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index a265d35838d..6c41c028df1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -25,18 +25,24 @@ * {@link Token} subtype designed for WebWhois sequence. * *

Between loops of a WebWhois sequence the only thing changing is the tld we - * are probing. As a result, we maintain the list of {@code topLevelDomains} and - * on each call to next, have our index looking at the next {@code topLevelDomain}.

+ * are probing. As a result, we maintain the list of {@code topLevelDomains} and on each call to + * next, have our index looking at the next {@code topLevelDomain}.

*/ public class WebWhoisToken extends Token { - /** For each top level domain (tld), we probe "prefix.tld". */ - private final static String PREFIX = "whois.nic."; + /** + * For each top level domain (tld), we probe "prefix.tld". + */ + private static final String PREFIX = "whois.nic."; - /** {@link ImmutableList} of all top level domains to be probed. */ + /** + * {@link ImmutableList} of all top level domains to be probed. + */ private final Iterator topLevelDomainsIterator; - /** Current index of {@code topLevelDomains} that represents tld we are probing. */ + /** + * Current index of {@code topLevelDomains} that represents tld we are probing. + */ private String currentDomain; @Inject @@ -46,20 +52,28 @@ public WebWhoisToken(@WebWhoisProtocol Iterator topLevelDomainsIterator) currentDomain = this.topLevelDomainsIterator.next(); } - /** Increments {@code domainsIndex} or resets it to reflect move to next top level domain. */ + /** + * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. + */ @Override public WebWhoisToken next() { currentDomain = topLevelDomainsIterator.next(); return this; } - /** Modifies message to reflect the new host coming from the new top level domain. */ + /** + * Modifies message to reflect the new host coming from the new top level domain. + */ @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) throws UndeterminedStateException { + public OutboundMessageType modifyMessage(OutboundMessageType original) + throws UndeterminedStateException { return original.modifyMessage(host()); } - /** Returns host as the concatenation of fixed {@code prefix} and current value of {@code topLevelDomains}. */ + /** + * Returns host as the concatenation of fixed {@code prefix} and current value of {@code + * topLevelDomains}. + */ @Override public String host() { return PREFIX + currentDomain; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index f7857dd80f9..4c9bfe04fa4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -43,14 +43,16 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; + /** * Unit tests for {@link ProbingAction} subtypes * *

Attempts to test how well each {@link ProbingAction} works with an {@link ActionHandler} * subtype when receiving to all possible types of responses

- * */ + */ @RunWith(JUnit4.class) public class ProbingActionTest { + private static final String TEST_MESSAGE = "MESSAGE_TEST"; private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_MESSAGE_TEST"; private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; @@ -58,19 +60,20 @@ public class ProbingActionTest { private static final int TEST_PORT = 0; private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - - /** We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on {@link ProbingAction} */ + /** + * Used for testing how well probing step can create connection to blackbox server + */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + /** + * We use custom Test {@link ActionHandler} and {@link ConversionHandler} so test depends only on + * {@link ProbingAction} + */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = () -> testHandler; private Provider conversionHandlerProvider = () -> conversionHandler; - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - @Ignore @Test public void testBehavior_existingChannel() { @@ -152,10 +155,10 @@ public void testSuccess_newChannel() throws Exception { //Tests to see if message is properly sent to remote server nettyRule.assertReceivedMessage(TEST_MESSAGE); - future.syncUninterruptibly(); + future = future.syncUninterruptibly(); //Tests to see that, since server responds, we have set future to true assertThat(future.isSuccess()).isTrue(); - assertThat(((TestActionHandler)testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); + assertThat(((TestActionHandler) testHandler).getResponse().toString()).isEqualTo(TEST_MESSAGE); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 62d275c9b2c..fe92660dbeb 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -16,89 +16,70 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.testing.JUnitBackports.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; -import google.registry.monitoring.blackbox.TestUtils.ProbingSequenceTestToken; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; -import java.net.SocketAddress; -import org.joda.time.Duration; +import io.netty.channel.embedded.EmbeddedChannel; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; - +import org.mockito.Mockito; + +/** + * Unit Tests on {@link ProbingSequence} + * + *

First tests the construction of sequences and ensures the ordering is exactly how + * we expect it to be.

+ * + *

Then tests the execution of each step, by ensuring the methods treatment of any kind + * of response from the {@link ProbingStep}s or {@link ProbingAction}s is what is expected.

+ */ @RunWith(JUnit4.class) public class ProbingSequenceTest { - private final static String TEST_HOST = "TEST_HOST"; + /** + * Default mock {@link ProbingAction} returned when generating an action with a mockStep. + */ + private ProbingAction mockAction; - private Token testToken = new ProbingSequenceTestToken(); + /** + * Default mock {@link ProbingStep} that will usually return a {@code mockAction} on call to + * generate action. + */ + private ProbingStep mockStep; /** - * Custom {@link ProbingStep} subclass that acts as a mock - * step, so we can test how well {@link ProbingSequence} builds - * a linked list of {@link ProbingStep}s from their {@link Builder}s. + * Default mock {@link Token} that is passed into each {@link ProbingSequence} tested. */ - private static class TestStep extends ProbingStep { - private String marker; - private DuplexMessageTest message; - - /** We implement all abstract methods to simply return null, as we have no use for them here. */ - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return message; - } - - /** We want to be able to set and retrieve the bootstrap, as {@link ProbingSequence} does this. */ - @Override - Bootstrap bootstrap() { - return null; - } - - public TestStep(String marker) { - this.marker = marker; - message = new DuplexMessageTest(marker); - } - - /** - * On a call to accept, we modify the token to reflect what the current step is, so we can get - * from the token a string which represents each {@link ProbingStep} {@code marker} concatenated - * in order. - - @Override - public void accept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - if (!isLastStep) { - nextStep().accept(token); - } else { - ((TestStep)nextStep()).specialAccept(token); - } - } - */ - - /** We only invoke this on what we expect to be the firstRepeatedStep marked by the sequence. */ - public void specialAccept(Token token) { - ((ProbingSequenceTestToken) token).addToHost(marker); - return; - } + private Token testToken; + + @Before + public void setup() { + // To avoid a NullPointerException, we must have a protocol return persistent connection as + // false. + Protocol mockProtocol = Mockito.mock(Protocol.class); + doReturn(false).when(mockProtocol).persistentConnection(); + + mockAction = Mockito.mock(ProbingAction.class); + + //In order to avoid a NullPointerException, we must have the protocol returned that stores + // persistent connection as false. + mockStep = Mockito.mock(ProbingStep.class); + doReturn(mockProtocol).when(mockStep).protocol(); + + testToken = Mockito.mock(Token.class); } @Test public void testSequenceBasicConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addElement(firstStep) @@ -106,16 +87,17 @@ public void testSequenceBasicConstruction_Success() { .addElement(thirdStep) .build(); - sequence.start(); - - assertThat(testToken.host()).isEqualTo("firstsecondthirdfirst"); + assertThat(sequence.next()).isEqualTo(firstStep); + assertThat(sequence.next()).isEqualTo(secondStep); + assertThat(sequence.next()).isEqualTo(thirdStep); + assertThat(sequence.next()).isEqualTo(firstStep); } @Test public void testSequenceAdvancedConstruction_Success() { - ProbingStep firstStep = new TestStep("first"); - ProbingStep secondStep = new TestStep("second"); - ProbingStep thirdStep = new TestStep("third"); + ProbingStep firstStep = Mockito.mock(ProbingStep.class); + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) .addElement(thirdStep) @@ -125,9 +107,83 @@ public void testSequenceAdvancedConstruction_Success() { .addElement(firstStep) .build(); + assertThat(sequence.next()).isEqualTo(thirdStep); + assertThat(sequence.next()).isEqualTo(secondStep); + assertThat(sequence.next()).isEqualTo(firstStep); + assertThat(sequence.next()).isEqualTo(secondStep); + + } + + @Test + public void testRunStep_Success() throws UndeterminedStateException { + // Create channel for the purpose of generating channel futures. + EmbeddedChannel channel = new EmbeddedChannel(); + + //Always returns a succeeded future on call to mockAction. + doReturn(channel.newSucceededFuture()).when(mockAction).call(); + + // Has mockStep always return mockAction on call to generateAction + doReturn(mockAction).when(mockStep).generateAction(any(Token.class)); + + //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + + //Build testable sequence from mocked components. + ProbingSequence sequence = new ProbingSequence.Builder(testToken) + .addElement(mockStep) + .addElement(secondStep) + .build(); + sequence.start(); - assertThat(testToken.host()).isEqualTo("thirdsecondfirstsecond"); + assertThat(sequence.get()).isEqualTo(secondStep); + } + + @Test + public void testRunStep_FailureRunning() throws UndeterminedStateException { + // Create channel for the purpose of generating channel futures. + EmbeddedChannel channel = new EmbeddedChannel(); + + // Returns a failed future when calling the generated mock action. + doReturn(channel.newFailedFuture(new FailureException(""))).when(mockAction).call(); + + // Returns mock action on call to generate action for ProbingStep. + doReturn(mockAction).when(mockStep).generateAction(any(Token.class)); + + //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + + //Build testable sequence from mocked components. + ProbingSequence sequence = new ProbingSequence.Builder(testToken) + .addElement(mockStep) + .addElement(secondStep) + .build(); + + sequence.start(); + + assertThat(sequence.get()).isEqualTo(secondStep); + } + + + @Test + public void testRunStep_FailureGenerating() throws UndeterminedStateException { + // Create a mock first step that returns the dummy action when called to generate an action. + doThrow(UndeterminedStateException.class).when(mockStep).generateAction(any(Token.class)); + + //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + + //Build testable sequence from mocked components. + ProbingSequence sequence = new ProbingSequence.Builder(testToken) + .addElement(mockStep) + .addElement(secondStep) + .build(); + + // When there is an error in action, generating, the next step is immediately called in the same + // thread, so we expect a NullPointerException to be thrown in this thread. + assertThrows(NullPointerException.class, sequence::start); + + assertThat(sequence.get()).isEqualTo(secondStep); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index efcd2a026b8..81c7e31ce95 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -11,133 +11,89 @@ // 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.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; -import static google.registry.monitoring.blackbox.TestUtils.dummyStep; -import static google.registry.monitoring.blackbox.TestUtils.testStep; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +/** + * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific + * implementations + */ public class ProbingStepTest { - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - + /** + * Basic Constants necessary for tests + */ + private static final String ADDRESS_NAME = "TEST_ADDRESS"; + private static final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private static final int PROTOCOL_PORT = 0; + private static final String TEST_MESSAGE = "TEST_MESSAGE"; + private static final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + private static final LocalAddress address = new LocalAddress(ADDRESS_NAME); private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); private final Bootstrap bootstrap = new Bootstrap() .group(eventLoopGroup) .channel(LocalChannel.class); - - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ + /** + * Used for testing how well probing step can create connection to blackbox server + */ @Rule public NettyRule nettyRule = new NettyRule(eventLoopGroup); - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + /** + * The two main handlers we need in any test pipeline used that connects to {@link NettyRule's + * server} + **/ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(ADDRESS_NAME); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, SECONDARY_TEST_MESSAGE); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .setName(PROTOCOL_NAME) - .setPort(PROTOCOL_PORT) - .setPersistentConnection(false) - .build(); - } - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + @Test + public void testProbingActionGenerate_embeddedChannel() throws UndeterminedStateException { + // Sets up Protocol to represent existing channel connection. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) .setPort(PROTOCOL_PORT) .setPersistentConnection(true) .build(); - } - @Test - public void testProbingActionGenerate_embeddedChannel() throws UndeterminedStateException { - //setup - setupExistingProtocol(); - setupChannel(); - setupExistingChannelToken(); + // Sets up an embedded channel to contain the two handlers we created already. + EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); + channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); + + // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the + // ProbingStep generates an ExistingChannelAction. + Token testToken = new ExistingChannelToken(channel, SECONDARY_TEST_MESSAGE); + // Sets up generic {@link ProbingStep} that we are testing. ProbingStep testStep = ProbingStep.builder() - .setMessageTemplate(new DuplexMessageTest(TEST_MESSAGE)) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) .setBootstrap(bootstrap) .setDuration(Duration.ZERO) .setProtocol(testProtocol) @@ -156,22 +112,33 @@ public void testProbingActionGenerate_embeddedChannel() throws UndeterminedState @Test public void testProbingActionGenerate_newChannel() throws UndeterminedStateException { - //setup - setupNewProtocol(); - setupNewChannelToken(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + // Sets up Protocol for when we create a new channel. + Protocol testProtocol = Protocol.builder() + .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) + .setName(PROTOCOL_NAME) + .setPort(PROTOCOL_PORT) + .setPersistentConnection(false) + .build(); + // Sets up generic ProbingStep that we are testing. ProbingStep testStep = ProbingStep.builder() - .setMessageTemplate(new DuplexMessageTest(TEST_MESSAGE)) + .setMessageTemplate(new TestMessage(TEST_MESSAGE)) .setBootstrap(bootstrap) .setDuration(Duration.ZERO) .setProtocol(testProtocol) .build(); + // Sets up testToken to return arbitrary values, and no channel. Used when we create a new + // channel. + Token testToken = new NewChannelToken(ADDRESS_NAME); + + // Sets up server listening at LocalAddress so generated action can have successful connection. + nettyRule.setUpServer(address); + ProbingAction testAction = testStep.generateAction(testToken); ChannelFuture connectionFuture = testAction.channel().attr(CONNECTION_FUTURE_KEY).get(); - connectionFuture.syncUninterruptibly(); + connectionFuture = connectionFuture.syncUninterruptibly(); assertThat(connectionFuture.isSuccess()).isTrue(); assertThat(testAction.delay()).isEqualTo(Duration.ZERO); @@ -180,71 +147,5 @@ public void testProbingActionGenerate_newChannel() throws UndeterminedStateExcep assertThat(testAction.protocol()).isEqualTo(testProtocol); - - - } - - /* - @Test - public void testNewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - } - */ } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java index 46615a506fb..008c69d8fbf 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java @@ -26,7 +26,8 @@ import io.netty.channel.nio.NioEventLoopGroup; /** - * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to perform + * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to + * perform */ public abstract class TestServer { @@ -34,7 +35,8 @@ public abstract class TestServer { this(new NioEventLoopGroup(1), localAddress, handlers); } - TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, + ImmutableList handlers) { //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override @@ -44,12 +46,13 @@ protected void initChannel(LocalChannel ch) { } } }; - //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using LocalServerChannel class + //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using + // LocalServerChannel class ServerBootstrap serverBootstrap = new ServerBootstrap() - .group(eventLoopGroup) - .channel(LocalServerChannel.class) - .childHandler(serverInitializer); + .group(eventLoopGroup) + .channel(LocalServerChannel.class) + .childHandler(serverInitializer); ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java index 28b36190a7e..6b8d6ff24b6 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; @@ -36,30 +37,40 @@ * {@link TestServer} subtype that performs WebWhois Services Expected * *

It will either redirect the client to the correct location if given the - * requisite redirect input, give the client a successful response if they give - * the expected final destination, or give the client an error message if given - * an unexpected host location

+ * requisite redirect input, give the client a successful response if they give the expected final + * destination, or give the client an error message if given an unexpected host location

*/ public class WebWhoisServer extends TestServer { - public WebWhoisServer(LocalAddress localAddress, ImmutableList handlers) { + public WebWhoisServer(LocalAddress localAddress, + ImmutableList handlers) { super(localAddress, handlers); } - public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { + public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, + ImmutableList handlers) { super(eventLoopGroup, localAddress, handlers); } - /** Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the HttpRequestMessage object through pipeline */ - public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + /** + * Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the + * HttpRequestMessage object through pipeline + */ + public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, + LocalAddress localAddress, String redirectInput, String destinationInput) { return new WebWhoisServer( eventLoopGroup, localAddress, ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) ); } - /** Creates server that sends exactly what we expect a remote server to send as a response, by sending the {@link ByteBuf} of the response through pipeline */ - public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, String redirectInput, String destinationInput) { + + /** + * Creates server that sends exactly what we expect a remote server to send as a response, by + * sending the {@link ByteBuf} of the response through pipeline + */ + public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, + String redirectInput, String destinationInput) { return new WebWhoisServer( eventLoopGroup, localAddress, @@ -75,31 +86,37 @@ public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddr */ @Sharable static class RedirectHandler extends SimpleChannelInboundHandler { + private String redirectInput; private String destinationInput; /** - * - * @param redirectInput - Server will send back redirect to {@code destinationInput} when receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response when receiving a request with this host location + * @param redirectInput - Server will send back redirect to {@code destinationInput} when + * receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response + * when receiving a request with this host location */ public RedirectHandler(String redirectInput, String destinationInput) { this.redirectInput = redirectInput; this.destinationInput = destinationInput; } - /** Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on what header location is */ + /** + * Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on + * what header location is + */ @Override public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, false)); + response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true)); } else if (request.headers().get("host").equals(destinationInput)) { response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); } - ctx.channel().writeAndFlush(response); + ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index cd9c5adcf5e..e18c853a3f0 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -14,49 +14,27 @@ package google.registry.monitoring.blackbox; -import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.US_ASCII; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.tokens.Token; -import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.concurrent.DefaultPromise; -import java.net.SocketAddress; -import javax.annotation.Nullable; -import javax.inject.Provider; -import org.joda.time.Duration; -/** Utility class for various helper methods used in testing. */ +/** + * Utility class for various helper methods used in testing. + */ public class TestUtils { - static FullHttpRequest makeHttpPostRequest(String content, String host, String path) { - ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII)); - FullHttpRequest request = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, path, buf); - request - .headers() - .set("user-agent", "Proxy") - .set("host", host) - .setInt("content-length", buf.readableBytes()); - return request; - } - public static FullHttpRequest makeHttpGetRequest(String host, String path) { FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); @@ -77,140 +55,33 @@ public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) { return response; } - /** Creates HttpResponse given status, redirection location, and other necessary inputs */ + /** + * Creates HttpResponse given status, redirection location, and other necessary inputs + */ public static FullHttpResponse makeRedirectResponse( - HttpResponseStatus status, String location, boolean keepAlive, boolean hsts) { + HttpResponseStatus status, String location, boolean keepAlive) { FullHttpResponse response = makeHttpResponse("", status); - response.headers().set("content-type", "text/plain").set("content-length", "0"); + response.headers().set("content-type", "text/plain"); if (location != null) { response.headers().set("location", location); } if (keepAlive) { response.headers().set("connection", "keep-alive"); } - if (hsts) { - response.headers().set("Strict-Transport-Security", "max-age=31536000"); - } return response; } - public static FullHttpRequest makeWhoisHttpRequest( - String content, String host, String path, String accessToken) { - FullHttpRequest request = makeHttpPostRequest(content, host, path); - request - .headers() - .set("authorization", "Bearer " + accessToken) - .set("content-type", "text/plain") - .set("accept", "text/plain"); - return request; - } - - public static FullHttpResponse makeWhoisHttpResponse(String content, HttpResponseStatus status) { - FullHttpResponse response = makeHttpResponse(content, status); - response.headers().set("content-type", "text/plain"); - return response; - } - - /** {@link Provider} test subtype for the purpose of easily adding requisite {@link ChannelHandler}s to pipeline */ - public static class TestProvider implements Provider { - - private E obj; - - public TestProvider(E obj) { - this.obj = obj; - } - - @Override - public E get() { - return obj; - } - } - - /** {@link InboundMessageType} and {@link OutboundMessageType} type for the purpose of containing String messages to be passed down channel */ - public static class DuplexMessageTest implements OutboundMessageType, InboundMessageType { - - String message; - - public DuplexMessageTest() { - message = ""; - } - - public DuplexMessageTest(String msg) { - message = msg; - } - - @Override - public String toString() { - return message; - } - - @Override - public OutboundMessageType modifyMessage(String... args) throws UndeterminedStateException { - message = args[0]; - return this; - } - } - - /** {@link ProbingStep} subclass that performs probing Steps functions, without time delay */ - public static ProbingStep testStep(Protocol protocol, String testMessage, Bootstrap bootstrap, SocketAddress address) { - return ProbingStep.builder() - .setProtocol(protocol) - .setDuration(Duration.ZERO) - .setMessageTemplate(new DuplexMessageTest(testMessage)) - .setBootstrap(bootstrap) - .build(); - - } - public static ProbingStep dummyStep(EventLoopGroup eventLoopGroup) { - return new DummyStep(eventLoopGroup); - } - - /** {@link ProbingStep} subclass that is solely used to note when the previous {@link ProbingStep} has completed its action */ - public static class DummyStep extends ProbingStep { - private DefaultPromise future; - - public DummyStep(EventLoopGroup eventLoopGroup) { - future = new DefaultPromise(eventLoopGroup.next()) { - }; - } - - @Override - Duration duration() { - return null; - } - - @Override - Protocol protocol() { - return null; - } - - @Override - OutboundMessageType messageTemplate() { - return null; - } - - @Override - Bootstrap bootstrap() { - return null; - } - - public DefaultPromise getFuture() { - return future; - } - - @Override - public String toString() { - return "Dummy Step"; - } - } + /** + * Basic outline for {@link Token} instances to be used in tests + */ + abstract static class TestToken extends Token { - /** Basic outline for {@link Token} instances to be used in tests */ - private static abstract class TestToken extends Token { protected String host; protected TestToken(String host) { this.host = host; } + @Override public Token next() { return this; @@ -229,73 +100,31 @@ public String host() { } - /** {@link TestToken} instance that creates new channel */ + /** + * {@link TestToken} instance that creates new channel + */ public static class NewChannelToken extends TestToken { + public NewChannelToken(String host) { super(host); } + @Override public Channel channel() { return null; } } - /** {@link TestToken} instance that passes in existing channel */ + /** + * {@link TestToken} instance that passes in existing channel + */ public static class ExistingChannelToken extends TestToken { - private Channel channel; + public ExistingChannelToken(Channel channel, String host) { super(host); this.channel = channel; } - @Override - public Channel channel() { - return channel; - } - } - - /** {@link TestToken} instance that creates new channel */ - public static class ProbingSequenceTestToken extends TestToken { - public ProbingSequenceTestToken() { - super(""); - } - @Override - public Channel channel() { - return null; - } - - public void addToHost(String suffix) { - host += suffix; - } - - } - - /** - * Compares two {@link FullHttpMessage} for equivalency. - * - *

This method is needed because an HTTP message decoded and aggregated from inbound {@link - * ByteBuf} is of a different class than the one written to the outbound {@link ByteBuf}, and The - * {@link ByteBuf} implementations that hold the content of the HTTP messages are different, even - * though the actual content, headers, etc are the same. - * - *

This method is not type-safe, msg1 & msg2 can be a request and a response, respectively. Do - * not use this method directly. - */ - private static void assertHttpMessageEquivalent(HttpMessage msg1, HttpMessage msg2) { - assertThat(msg1.protocolVersion()).isEqualTo(msg2.protocolVersion()); - assertThat(msg1.headers()).isEqualTo(msg2.headers()); - if (msg1 instanceof FullHttpRequest && msg2 instanceof FullHttpRequest) { - assertThat(((FullHttpRequest) msg1).content()).isEqualTo(((FullHttpRequest) msg2).content()); - } - } - - public static void assertHttpResponseEquivalent(FullHttpResponse res1, FullHttpResponse res2) { - assertThat(res1.status()).isEqualTo(res2.status()); - assertHttpMessageEquivalent(res1, res2); - } - - public static void assertHttpRequestEquivalent(HttpRequest req1, HttpRequest req2) { - assertHttpMessageEquivalent(req1, req2); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index c9d337d6ad8..987abbfd7dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -28,15 +28,17 @@ import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to - * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link + * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} + * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** Handles inbound conversion */ + /** + * Handles inbound conversion + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; @@ -44,7 +46,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception buf.release(); } - /** Handles outbound conversion */ + /** + * Handles outbound conversion + */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index 86b54d9a07d..f13e129a512 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -52,11 +52,18 @@ * Helper for setting up and testing client / server connection with netty. * *

Code based on and almost identical to {@code NettyRule} in the proxy. - * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest}

+ * Used in {@link SslClientInitializerTest}, {@link ProbingActionTest}, and {@link ProbingStepTest} + *

*/ public final class NettyRule extends ExternalResource { + private final EventLoopGroup eventLoopGroup; + // Handler attached to server's channel to record the request received. + private EchoHandler echoHandler; + // Handler attached to client's channel to record the response received. + private DumpHandler dumpHandler; + private Channel channel; // All I/O operations are done inside the single thread within this event loop group, which is // different from the main test thread. Therefore synchronizations are required to make sure that @@ -64,30 +71,30 @@ public final class NettyRule extends ExternalResource { public NettyRule() { eventLoopGroup = new NioEventLoopGroup(1); } + public NettyRule(EventLoopGroup e) { eventLoopGroup = e; } - private final EventLoopGroup eventLoopGroup; - private WebWhoisServer webWhoisServer; - - // Handler attached to server's channel to record the request received. - private EchoHandler echoHandler; - // Handler attached to client's channel to record the response received. - private DumpHandler dumpHandler; - - private Channel channel; + private static void writeToChannelAndFlush(Channel channel, String data) { + ChannelFuture unusedFuture = + channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); + } - /** Sets up a server channel bound to the given local address. */ + /** + * Sets up a server channel bound to the given local address. + */ public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - webWhoisServer = new WebWhoisServer(eventLoopGroup, localAddress, + new WebWhoisServer(eventLoopGroup, localAddress, ImmutableList.builder().add(handlers).add(echoHandler).build()); } - /** Sets up a client channel connecting to the give local address. */ + /** + * Sets up a client channel connecting to the give local address. + */ void setUpClient( LocalAddress localAddress, Protocol protocol, @@ -121,7 +128,9 @@ private void checkReady() { checkState(channel != null, "Must call setUpClient to finish NettyRule setup"); } - /** Test that custom setup to send message to current server sends right message */ + /** + * Test that custom setup to send message to current server sends right message + */ public void assertReceivedMessage(String message) throws Exception { assertThat(echoHandler.getRequestFuture().get()).isEqualTo(message); @@ -130,9 +139,9 @@ public void assertReceivedMessage(String message) throws Exception { /** * Test that a message can go through, both inbound and outbound. * - *

The client writes the message to the server, which echos it back and saves the string in its - * promise. The client receives the echo and saves it in its promise. All these activities happens - * in the I/O thread, and this call itself returns immediately. + *

The client writes the message to the server, which echos it back and saves the string in + * its promise. The client receives the echo and saves it in its promise. All these activities + * happens in the I/O thread, and this call itself returns immediately. */ void assertThatMessagesWork() throws Exception { checkReady(); @@ -162,6 +171,10 @@ ThrowableSubject assertThatClientRootCause() { assertThrows(ExecutionException.class, () -> dumpHandler.getResponseFuture().get()))); } + @Override + protected void after() { + Future unusedFuture = eventLoopGroup.shutdownGracefully(); + } /** * A handler that echoes back its inbound message. The message is also saved in a promise for @@ -196,7 +209,9 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E } } - /** A handler that dumps its inbound message to a promise that can be inspected later. */ + /** + * A handler that dumps its inbound message to a promise that can be inspected later. + */ private static class DumpHandler extends ChannelInboundHandlerAdapter { private final CompletableFuture responseFuture = new CompletableFuture<>(); @@ -217,21 +232,13 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception responseFuture.complete(response); } - /** Saves any inbound error into the failure cause of the promise. */ + /** + * Saves any inbound error into the failure cause of the promise. + */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.channel().closeFuture().addListener(f -> responseFuture.completeExceptionally(cause)); } } - - @Override - protected void after() { - Future unusedFuture = eventLoopGroup.shutdownGracefully(); - } - - private static void writeToChannelAndFlush(Channel channel, String data) { - ChannelFuture unusedFuture = - channel.writeAndFlush(Unpooled.wrappedBuffer(data.getBytes(US_ASCII))); - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java index 523fb228752..2a9f9758e09 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/SslClientInitializerTest.java @@ -62,37 +62,41 @@ @RunWith(Parameterized.class) public class SslClientInitializerTest { - /** Fake host to test if the SSL engine gets the correct peer host. */ + /** + * Fake host to test if the SSL engine gets the correct peer host. + */ private static final String SSL_HOST = "www.example.tld"; - /** Fake port to test if the SSL engine gets the correct peer port. */ + /** + * Fake port to test if the SSL engine gets the correct peer port. + */ private static final int SSL_PORT = 12345; - + /** + * Fake protocol saved in channel attribute. + */ + private static final Protocol PROTOCOL = Protocol.builder() + .setName("ssl") + .setPort(SSL_PORT) + .setHandlerProviders(ImmutableList.of()) + .setPersistentConnection(false) + .build(); @Rule public NettyRule nettyRule = new NettyRule(); - @Parameter(0) public SslProvider sslProvider; + /** + * Saves the SNI hostname received by the server, if sent by the client. + */ + private String sniHostReceived; // We do our best effort to test all available SSL providers. @Parameters(name = "{0}") public static SslProvider[] data() { return OpenSsl.isAvailable() - ? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL} - : new SslProvider[] {SslProvider.JDK}; + ? new SslProvider[]{SslProvider.JDK, SslProvider.OPENSSL} + : new SslProvider[]{SslProvider.JDK}; } - /** Saves the SNI hostname received by the server, if sent by the client. */ - private String sniHostReceived; - - /** Fake protocol saved in channel attribute. */ - private final static Protocol PROTOCOL = Protocol.builder() - .setName("ssl") - .setPort(SSL_PORT) - .setHandlerProviders(ImmutableList.of()) - .setPersistentConnection(false) - .build(); - private ChannelHandler getServerHandler(PrivateKey privateKey, X509Certificate certificate) throws Exception { SslContext sslContext = SslContextBuilder.forServer(privateKey, certificate).build(); @@ -166,7 +170,7 @@ public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); @@ -195,7 +199,7 @@ public void testFailure_customTrustManager_wrongHostnameInCertificate() throws E // Set up the client to trust the self signed cert used to sign the cert that server provides. SslClientInitializer sslClientInitializer = - new SslClientInitializer<>(sslProvider, new X509Certificate[] {ssc.cert()}); + new SslClientInitializer<>(sslProvider, new X509Certificate[]{ssc.cert()}); nettyRule.setUpClient(localAddress, PROTOCOL, SSL_HOST, sslClientInitializer); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 95b06e623d1..19e608c97d2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -20,8 +20,8 @@ import io.netty.channel.ChannelHandlerContext; /** - * Concrete implementation of {@link ActionHandler} that does nothing different from - * parent class other than store and return the {@code inboundMessage} + * Concrete implementation of {@link ActionHandler} that does nothing different from parent class + * other than store and return the {@code inboundMessage} */ public class TestActionHandler extends ActionHandler { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 33eb190a66a..223f494f737 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -17,8 +17,8 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeHttpGetRequest; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; @@ -39,7 +39,6 @@ import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import javax.inject.Provider; -import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -54,14 +53,9 @@ public class WebWhoisActionHandlerTest { private static final int HTTP_PORT = 80; - private static final int HTTPS_PORT = 443; private static final String HTTP_REDIRECT = "http://"; - private static final String HTTPS_REDIRECT = "https://"; - private static final String REDIRECT_HOST = "www.example.com"; - private static final String REDIRECT_PATH = "/test/path"; private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private static final Duration DEFAULT_DURATION = new Duration(0L); private final Protocol STANDARD_PROTOCOL = Protocol.builder() .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( null, null, null, null))) @@ -177,6 +171,7 @@ public void testBasic_responseFailure_badRequest() { assertThat(future.cause() instanceof FailureException).isTrue(); } + @SuppressWarnings("CheckReturnValue") @Test public void testBasic_responseFailure_badURL() { //setup diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index 847cd052663..61d27460f4c 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -16,12 +16,8 @@ import static com.google.common.truth.Truth.assertThat; -import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import google.registry.util.AbstractCircularLinkedListIterator; import google.registry.util.DefaultCircularLinkedListIterator; import java.util.Iterator; import org.junit.Test; From 39f2f08cc1235fd9f689c5ccebe50737c6b9d2b9 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 287/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 3 +- .../google/registry/xjc/package-info.java | 3 +- .../monitoring/blackbox/NewChannelAction.java | 136 ++++++++++++++++++ .../registry/monitoring/blackbox/Prober.java | 23 +-- .../handlers/ServerSideException.java | 15 ++ .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 9 files changed, 164 insertions(+), 24 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index ddff37c6807..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,3 +14,4 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.ui; + diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 5b5456585cc..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. @@ -14,3 +14,4 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.xjc; + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..0ba3a0c22be --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 433d7361d5b..333330207f1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,30 +14,17 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by - * Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** - * Main Dagger Component - */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() - .build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From 8b8aff0062185dfdd9ab86bfe760ae802273b176 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:58:52 -0400 Subject: [PATCH 288/337] Fixed changes suggested by CydeWeys --- .../main/java/google/registry/monitoring/blackbox/Protocol.java | 1 + 1 file changed, 1 insertion(+) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index ae7b3ec0f79..f37078f8f94 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -76,3 +76,4 @@ public abstract Builder setHandlerProviders( public abstract Protocol build(); } } + From a359887b703ce83d63a8428b3b54a4ee4bcdd761 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 289/337] Added missing license headers and JavaDoc --- .../blackbox/handlers/ServerSideException.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java index 5d3addb920e..441062a9e7b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; /** @@ -12,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} From da40cb75d6084871ed0904ebcc1532d210877bfb Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 290/337] Minor fix in NewChannelAction JavaDoc --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..1e7578d5679 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; - import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -28,8 +27,7 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) */ @AutoValue public abstract class NewChannelAction extends ProbingAction { From e1b6a021232b01e19d81194cb207472bb012e2fb Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 13:33:23 -0400 Subject: [PATCH 291/337] Minor Style Fix --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 ---- .../java/google/registry/monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/handlers/WebWhoisActionHandler.java | 2 -- 3 files changed, 7 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..84cf75492f2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -52,7 +52,6 @@ public Channel channel() { return this.channel; } - @Override public abstract Builder toBuilder(); @@ -120,7 +119,6 @@ public static NewChannelAction.Builder builder() return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -129,6 +127,4 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index f37078f8f94..ae7b3ec0f79 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -76,4 +76,3 @@ public abstract Builder setHandlerProviders( public abstract Protocol build(); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index c0f7ce8ae78..9df4c98cc87 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -181,7 +181,5 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } } - - } From 7eb4e4aa3c4cbbf5ea21c3d80885836be037a33e Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 292/337] Full WebWhoIs Sequence Added --- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 17 +- .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 12 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 +++++ .../exceptions/EppClientException.java | 29 +++ .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../ServerSideException.java | 4 +- .../blackbox/handlers/MessageHandler.java | 6 + .../blackbox/ProbingSequenceStepTest.java | 219 ++++++++++++++++++ .../monitoring/blackbox/TokenTest.java | 60 +++++ .../blackbox/handlers/ConversionHandler.java | 23 +- 16 files changed, 600 insertions(+), 30 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 84cf75492f2..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -52,6 +53,7 @@ public Channel channel() { return this.channel; } + @Override public abstract Builder toBuilder(); @@ -83,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -116,9 +118,10 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } + @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -127,4 +130,6 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } + } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 333330207f1..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,16 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index ae7b3ec0f79..294a4a1b27a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -75,4 +75,16 @@ public abstract Builder setHandlerProviders( public abstract Protocol build(); } + + @Override + public String toString() { + return String.format( + "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", + name(), + port(), + handlerProviders(), + persistentConnection() + ); + } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index e676333489e..6b6946c6731 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,8 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. + * Base exception class for all instances when the Status of the task performed is ERROR */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index d1028018602..6116e77040b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is FAILURE. + * Base exception class for all instances when the Status of the task performed is ERROR */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java new file mode 100644 index 00000000000..7a713017072 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java @@ -0,0 +1,219 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.TestUtils.TestStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.handlers.ConversionHandler; +import google.registry.monitoring.blackbox.handlers.NettyRule; +import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.junit.Rule; +import org.junit.Test; + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + + /** Used for testing how well probing step can create connection to blackbox server */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + + + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ + private ProbingSequence testSequence; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); + dummyStep = new DummyStep(testProtocol, eventLoopGroup); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(false) + .build(); + } + + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(true) + .build(); + } + + /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ + private void setupSequence() { + testSequence = new ProbingSequence.Builder() + .eventLoopGroup(eventLoopGroup) + .setClass(LocalChannel.class) + .addStep(firstStep) + .makeFirstRepeated() + .addStep(dummyStep) + .build(); + } + + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //there should be no next step + assertThat(firstStep.nextStep()).isNull(); + + //we expect that this exception be thrown + assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); + + } + + @Test + public void testWithSequence_NewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupSequence(); + setupNewChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupSequence(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java new file mode 100644 index 00000000000..ef5cba5b60d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -0,0 +1,60 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + */ +@RunWith(JUnit4.class) +public class TokenTest { + + private static String PREFIX = "whois.nic."; + private static String TEST_STARTER = "starter"; + private static String TEST_DOMAIN = "test"; + + public Token webToken = new WebWhoisToken(TEST_DOMAIN); + + @Test + public void testWebToken_MessageModificationSuccess() { + //creates Request message with header + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + message.headers().set("host", TEST_STARTER); + + //attempts to use Token's method for modifying the method based on its stored host + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { + throw new RuntimeException(e); + } + + + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 987abbfd7dc..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,38 +17,31 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link - * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to + * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** - * Handles inbound conversion - */ + /** Handles inbound conversion */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } - /** - * Handles outbound conversion - */ + /** Handles outbound conversion */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { From 198b17e7ad39bd2c7d1b19a608b7d40daf69357b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 293/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 ++++++++++++------- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/ProbingSequence.java | 1 - .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 -- .../monitoring/blackbox/Tokens/Token.java | 4 ++- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../exceptions/EppClientException.java | 29 ----------------- .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++++-- 11 files changed, 44 insertions(+), 53 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 6dedc33fae0..69043665d16 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -182,4 +182,3 @@ public ProbingSequence build() { } } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 294a4a1b27a..d458e5cc4da 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -87,4 +87,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} From 8762baa022384f7ecf5fd7c609f896ffa2771da8 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 294/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 ------ .../monitoring/blackbox/NewChannelAction.java | 144 ------------------ .../registry/monitoring/blackbox/Prober.java | 20 +-- .../monitoring/blackbox/ProbingStepWeb.java | 45 ------ .../monitoring/blackbox/TokenModule.java | 35 ----- .../monitoring/blackbox/Tokens/Token.java | 47 ------ .../blackbox/Tokens/WebWhoisToken.java | 54 ------- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 ---- .../blackbox/handlers/MessageHandler.java | 24 --- 11 files changed, 9 insertions(+), 441 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} From bc54d3ccd34101b55bf9017b361a05c76bf6b521 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:05:59 -0400 Subject: [PATCH 295/337] Updated build.gradle file --- .../blackbox/ProbingSequenceStepTest.java | 219 ------------------ 1 file changed, 219 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java deleted file mode 100644 index 7a713017072..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.TestUtils.TestStep; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.handlers.ConversionHandler; -import google.registry.monitoring.blackbox.handlers.NettyRule; -import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; -import org.junit.Rule; -import org.junit.Test; - -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { - - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ - private ProbingSequence testSequence; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); - dummyStep = new DummyStep(testProtocol, eventLoopGroup); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(false) - .build(); - } - - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(true) - .build(); - } - - /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ - private void setupSequence() { - testSequence = new ProbingSequence.Builder() - .eventLoopGroup(eventLoopGroup) - .setClass(LocalChannel.class) - .addStep(firstStep) - .makeFirstRepeated() - .addStep(dummyStep) - .build(); - } - - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.nextStep()).isNull(); - - //we expect that this exception be thrown - assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); - - } - - @Test - public void testWithSequence_NewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupSequence(); - setupNewChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupSequence(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - - } -} From e564292a71107a1f05cc5cdeeff631290f5c3da5 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 296/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From be4bbc6588316c1a7f1ab786bdb5f4ca4007b441 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:54:13 -0400 Subject: [PATCH 297/337] Updated WebWhois tests. --- .../registry/monitoring/blackbox/TokenTest.java | 13 +++++++------ .../blackbox/handlers/ConversionHandler.java | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..67963805733 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,10 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; @@ -34,20 +35,20 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..a8506a996a9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -37,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } From 77ea13a11c799feaa7107cc6ab6478a5cfca1627 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 298/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- .../registry/monitoring/blackbox/Prober.java | 9 ++++-- .../exceptions/InternalException.java | 30 ------------------ .../exceptions/ResponseException.java | 29 ----------------- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../monitoring/blackbox/TokenTest.java | 8 ++--- 9 files changed, 9 insertions(+), 71 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..307afd34d81 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +29,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { @@ -49,7 +47,7 @@ public void testWebToken_MessageModificationSuccess() { try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } From d44fe2302ebd5aaf3119cdce6ef6067664a242aa Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 299/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/handlers/ConversionHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index a8506a996a9..196141bb875 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { From e2ae27cec48d48f7ef463d2d741d61f54bb4f69a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 5 Aug 2019 16:16:36 -0400 Subject: [PATCH 300/337] Refactored ProbingAction to minimize number of unnecessary methods --- .../main/java/google/registry/monitoring/blackbox/Prober.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 307afd34d81..e12d1f0f522 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; import java.util.Set; @@ -29,7 +30,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); + Set sequences = proberComponent.sequences(); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { From b7e7bda56fa678ee6b2f324fe586c5acd57882b0 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 15:45:32 -0400 Subject: [PATCH 301/337] Modified tests for WebWhois according to changes suggested by laijiang. --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/TokenTest.java | 59 ------------------- .../blackbox/handlers/ConversionHandler.java | 6 +- 3 files changed, 4 insertions(+), 64 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index e12d1f0f522..5ca423c29cc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -30,7 +29,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.sequences(); + ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java deleted file mode 100644 index 295bb809a13..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) - */ -@RunWith(JUnit4.class) -public class TokenTest { - - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - - public Token webToken = new WebWhoisToken(TEST_DOMAINS); - - @Test - public void testWebToken_MessageModificationSuccess() { - //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); - - //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { - throw new RuntimeException(e); - } - - - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 196141bb875..c9d337d6ad8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -32,7 +32,7 @@ * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +40,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } From 6917e08e4c28bbd1c4e2e92601042412d161a959 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 16 Jul 2019 11:03:40 -0400 Subject: [PATCH 302/337] Rebased to Master and added in modified Handlers and ProbingAction --- .../java/google/registry/ui/package-info.java | 2 +- .../google/registry/xjc/package-info.java | 2 +- prober/build.gradle | 5 - .../monitoring/blackbox/NewChannelAction.java | 136 +++++++ .../registry/monitoring/blackbox/Prober.java | 19 +- .../monitoring/blackbox/ProbingAction.java | 337 ++++++------------ .../handlers/ServerSideException.java | 15 + .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 152 +++----- .../blackbox/messages/HttpRequestMessage.java | 69 +--- .../messages/HttpResponseMessage.java | 40 +-- .../proxy/handler/SslClientInitializer.java | 2 +- .../registry/proxy/handler/NettyRule.java | 2 +- .../handler/SslClientInitializerTest.java | 2 +- .../handler/SslInitializerTestUtils.java | 2 +- 15 files changed, 350 insertions(+), 444 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..d65a45f3ac3 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..15f19b47989 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/prober/build.gradle b/prober/build.gradle index 3652390d0ba..e1e1e1144b3 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -20,8 +20,6 @@ dependencies { def deps = rootProject.dependencyMap compile deps['com.google.auto.value:auto-value-annotations'] - compile deps['com.google.code.findbugs:jsr305'] - compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] @@ -33,9 +31,6 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] - compile deps['org.bouncycastle:bcpkix-jdk15on'] - compile deps['org.bouncycastle:bcprov-jdk15on'] - compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java new file mode 100644 index 00000000000..0ba3a0c22be --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -0,0 +1,136 @@ +// Copyright 2019 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.monitoring.blackbox; + + +import com.google.auto.value.AutoValue; +import com.google.common.flogger.FluentLogger; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPromise; +import io.netty.channel.local.LocalAddress; + +/** + *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters + * + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel + */ +@AutoValue +public abstract class NewChannelAction extends ProbingAction { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + /** Default {@link LocalAddress} when not initialized in {@code Builder} */ + private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); + + /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + public abstract LocalAddress address(); + + /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + private Channel channel; + + /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + abstract Bootstrap bootstrap(); + + /** {@link Channel} object instantiated in {@code call()} */ + @Override + public Channel channel() { + return this.channel; + } + + + @Override + public abstract Builder toBuilder(); + + /** + * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance + * + * @return ChannelFuture instance that is set to success when previous action has + * finished and requisite time as passed + */ + @Override + public ChannelFuture call() { + + //Calls on bootstrap method + Bootstrap bootstrap = bootstrap(); + bootstrap.handler( + new ChannelInitializer() { + @Override + protected void initChannel(C outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROBING_ACTION_KEY, this); + + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + + ChannelFuture connectionFuture; + + if (!host().equals("")) { + connectionFuture = bootstrap.connect(host(), protocol().port()); + } else { + connectionFuture = bootstrap.connect(address()); + } + + //ChannelPromise that we return + ChannelPromise finished = connectionFuture.channel().newPromise(); + + //set current channel to one associated with connectionFuture + this.channel = connectionFuture.channel(); + + //When connection is established call super.call and set returned listener to success + connectionFuture.addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + ChannelFuture future = super.call(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + public static NewChannelAction.Builder builder() { + return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + } + + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder + public abstract NewChannelAction.Builder bootstrap(Bootstrap value); + + public abstract NewChannelAction.Builder address(LocalAddress value); + + } + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 5ca423c29cc..333330207f1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,26 +14,17 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import com.google.common.collect.ImmutableMap; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which constructs the ProbingSequences then runs them */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - + //TODO: Create ImmutableMap between port numbers and protocols with Dagger + public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + //TODO: Create and run probing sequences public static void main(String[] args) { - - //Obtains WebWhois Sequence provided by proberComponent - ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); - - //Tells Sequences to start running - for (ProbingSequence sequence : sequences) { - sequence.start(); - } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 36413b73452..2441debb12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,300 +14,173 @@ package google.registry.monitoring.blackbox; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; -import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.bootstrap.Bootstrap; +import io.netty.util.AttributeKey; +import java.util.concurrent.TimeUnit; +import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; -import io.netty.util.AttributeKey; import io.netty.util.HashedWheelTimer; import io.netty.util.Timer; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import javax.inject.Provider; -import org.joda.time.Duration; /** - * AutoValue class that represents action generated by {@link ProbingStep} + *Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when - * the task has been completed

+ * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the + * task has been completed

* - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type - * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall - * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the - * details of that connection.

+ *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. + * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} + * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes - * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when - * informed that the connection is successful. If the channel is supplied, the connection future is - * automatically set to successful.

+ *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and + * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send + * {@link OutboundMessageType} instance specified down the pipeline in the channel.

*/ -@AutoValue + public abstract class ProbingAction implements Callable { - /** - * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when - * channel is active. - */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey - .valueOf("CONNECTION_FUTURE_KEY"); - /** - * {@link AttributeKey} in channel that gives the information of the channel's host. - */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey - .valueOf("REMOTE_ADDRESS_KEY"); private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** - * {@link Timer} that rate limits probing - */ - private static final Timer timer = new HashedWheelTimer(); - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); - } + /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ + public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); + /** - * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified - * - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified - */ - private static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } + * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the + * last {@link ChannelHandler} in the pipeline + * */ + private ActionHandler actionHandler; + + + /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ + private ActionHandler actionHandler() { + return actionHandler; } - /** - * Actual {@link Duration} of this delay - */ + /** {@link Timer} that rate limits probing */ + private static final Timer timer = new HashedWheelTimer(); + + + /** Actual {@link Duration} of this delay */ public abstract Duration delay(); - /** - * {@link OutboundMessageType} instance that we write and flush down pipeline to server - */ + /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ public abstract OutboundMessageType outboundMessage(); - /** - * {@link Channel} object that either created by or passed into this {@link ProbingAction} - * instance - */ - @Nullable + /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** - * Performs the work of the actual action - * - *

First, checks if channel is active by setting a listener to perform the bulk of the work - * when the connection future is successful.

- * - *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

- * - *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

- * - * @return {@link ChannelFuture} that denotes when the action has been successfully performed. - */ - - /** - * The {@link Protocol} instance that specifies type of connection - */ + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); - /** - * The hostname of the remote host we have a connection or will make a connection to - */ public abstract String host(); - /** - * Method that calls on {@code performAction} when it is certain channel connection is - * established. - */ - @Override - public ChannelFuture call() { - //ChannelPromise that we return - ChannelPromise finished = channel().newPromise(); - - //Ensures channel has been set up with connection future as an attribute - checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); - - //When connection is established call super.call and set returned listener to success - channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture connectionFuture) -> { - if (connectionFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - - ActionHandler actionHandler; - try { - actionHandler = channel().pipeline().get(ActionHandler.class); - } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw - // an UndeterminedStateException - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); - - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture unusedflushFuture = channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> { - if (future.isSuccess()) { - ChannelFuture unusedFuture = finished.setSuccess(); - } else { - ChannelFuture unusedFuture = finished.setFailure(future.cause()); - } - }, - //If we don't have a persistent connection, close the connection to this - // channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) { - logger.atInfo() - .log("Closed stale channel. Moving on to next ProbingStep"); - } else { - logger.atWarning() - .log( - "Could not close channel. Stale connection still exists" - + "."); - } - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(connectionFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); + public abstract String path(); + + public abstract , P extends ProbingAction> Builder toBuilder(); + + + /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ + private void informListeners(ChannelPromise finished) { + ChannelFuture channelFuture = actionHandler().getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> finished.setSuccess(), + future -> { + if (!protocol().persistentConnection()) { + + //If we created a new channel for this action, close the connection to the channel + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); } } ); - return finished; - } - - @Override - public final String toString() { - return String.format( - "ProbingAction with delay: %d\n" - + "outboundMessage: %s\n" - + "protocol: %s\n" - + "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); } - /** - * {@link AutoValue.Builder} that does work of creating connection when not already present. + * The method that sends the {@code outboundMessage} down the channel pipeline + * + * @return future that denotes when the action has been successfully performed */ - @AutoValue.Builder - public abstract static class Builder { - private Bootstrap bootstrap; + @Override + public ChannelFuture call() { - public Builder setBootstrap(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - return this; + //Sets Action Handler to appropriately the last channel in the pipeline + //Logs severe if the last channel in the pipeline is not + try { + this.actionHandler = (ActionHandler) this.channel().pipeline().last(); + } catch (ClassCastException exception) { + logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); } - public abstract Builder setDelay(Duration value); - - public abstract Builder setOutboundMessage(OutboundMessageType value); - - public abstract Builder setProtocol(Protocol value); - - public abstract Builder setHost(String value); + //ChannelPromise that we use to inform ProbingStep when we are finished. + ChannelPromise finished = channel().newPromise(); - public abstract Builder setChannel(Channel channel); + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished + if (!delay().equals(Duration.ZERO)) { + timer.newTimeout(timeout -> { + // Write appropriate message to pipeline + informListeners(finished); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); + } else { + //if no delay, just perform the next action, and inform ProbingStep when finished + informListeners(finished); + } - abstract Protocol protocol(); + return finished; + } - abstract Channel channel(); + public abstract static class Builder, P extends ProbingAction> { - abstract String host(); + public abstract B delay(Duration value); - abstract ProbingAction autoBuild(); + public abstract B outboundMessage(OutboundMessageType value); - public ProbingAction build() { - SocketAddress address; - try { - InetAddress hostAddress = InetAddress.getByName(host()); - address = new InetSocketAddress(hostAddress, protocol().port()); - } catch (UnknownHostException e) { - address = new LocalAddress(host()); - } + public abstract B protocol(Protocol value); - checkArgument(channel() == null ^ bootstrap == null, - "One and only one of bootstrap and channel must be supplied."); - //If a channel is supplied, nothing is needed to be done + public abstract B host(String value); - //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel() == null) { - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(Channel outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROTOCOL_KEY, protocol()) - .attr(REMOTE_ADDRESS_KEY, host()); + public abstract B path(String value); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap.connect(address); + public abstract P build(); - setChannel(connectionFuture.channel()); - connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); - } + } - //now we can actually build the ProbingAction - return autoBuild(); + /** + * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified + * + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified + */ + static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java new file mode 100644 index 00000000000..5d3addb920e --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -0,0 +1,15 @@ +package google.registry.monitoring.blackbox.handlers; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ServerSideException extends Exception { + + public ServerSideException(String msg) { + super(msg); + } + + public ServerSideException(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index c62668b19b2..9913f948944 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,8 +15,7 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -89,8 +88,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - Protocol protocol = channel.attr(PROTOCOL_KEY).get(); - String host = channel.attr(REMOTE_ADDRESS_KEY).get(); + ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); + Protocol protocol = action.protocol(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -105,7 +104,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), host, protocol.port()); + .newHandler(channel.alloc(), action.host(), protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 9df4c98cc87..21010f0e887 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,21 +14,24 @@ package google.registry.monitoring.blackbox.handlers; +import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; + import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; +import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.ConnectionException; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import io.netty.bootstrap.Bootstrap; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -36,72 +39,39 @@ import org.joda.time.Duration; /** - * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response - * implies a redirection it follows the redirection until either an Error Response is received, or - * {@link HttpResponseStatus.OK} is received

+ *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection + * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

*/ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Dagger injected components necessary for redirect responses: */ - - /** - * {@link Bootstrap} necessary for remaking connection on redirect response. - */ - private final Bootstrap bootstrap; - - /** - * {@link Protocol} for when redirected to http endpoint. - */ - private final Protocol httpWhoisProtocol; - - /** - * {@link Protocol} for when redirected to https endpoint. - */ - private final Protocol httpsWhoisProtocol; - - /** - * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. - */ - private final HttpRequestMessage requestMessage; - @Inject - public WebWhoisActionHandler( - @WebWhoisProtocol Bootstrap bootstrap, - @HttpWhoisProtocol Protocol httpWhoisProtocol, - @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage) { - - this.bootstrap = bootstrap; - this.httpWhoisProtocol = httpWhoisProtocol; - this.httpsWhoisProtocol = httpsWhoisProtocol; - this.requestMessage = requestMessage; - } + public WebWhoisActionHandler() {} /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, - * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a - * response indicating a Failure, or receives a redirection response, where it follows the - * redirects until receiving one of the previous three responses. + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error + * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws FailureException, UndeterminedStateException { + throws ServerSideException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status().equals(HttpResponseStatus.OK)) { + + if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); - //On success, we always pass message to ActionHandler's channelRead0 method. - super.channelRead0(ctx, msg); + finished.setSuccess(); - } else if (response.headers().get("location") != null) { + logger.atInfo().log("Response Received: " + response); + + } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { //Obtain url to be redirected to URL url; @@ -109,77 +79,59 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException( - "Redirected Location was invalid. Given Location was: " + response.headers() - .get("Location")); + throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); + int newPort = url.getDefaultPort(); - logger.atInfo().log(String - .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, - url.getDefaultPort(), newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol; - if (url.getProtocol().equals(httpWhoisProtocol.name())) { - newProtocol = httpWhoisProtocol; - } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { - newProtocol = httpsWhoisProtocol; - } else { - throw new FailureException( - "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); - } + Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - //Obtain HttpRequestMessage with modified headers to reflect new host and path. - HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); + //Obtain old ProbingAction, which we will use as a template for the new one + ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + + //Modify HttpRequestMessage sent to remote host to reflect new path and host + HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); + httpRequest.headers().set(HttpHeaderNames.HOST, newHost); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = ProbingAction.builder() - .setBootstrap(bootstrap) - .setProtocol(newProtocol) - .setOutboundMessage(httpRequest) - .setDelay(Duration.ZERO) - .setHost(newHost) + ProbingAction redirectedAction = oldAction.toBuilder() + .protocol(newProtocol) + .outboundMessage(httpRequest) + .delay(Duration.ZERO) + .host(newHost) + .path(newPath) .build(); + //Mainly for testing, to check the probing action was created appropriately + ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) { - logger.atInfo().log("Successfully Closed Connection."); - } else { - logger.atWarning().log("Channel was unsuccessfully closed."); - } - - //Once channel is closed, establish new connection to redirected host, and repeat - // same actions + logger.atInfo().log("Successfully Closed Connection"); + + //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell - // ProbingStep we can move on - secondFuture.addListener(f2 -> { - if (f2.isSuccess()) { - super.channelRead0(ctx, msg); - } else { - if (f2 instanceof FailureException) { - throw new FailureException(f2.cause()); - } else { - throw new UndeterminedStateException(f2.cause()); - } - } - - }); + //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + secondFuture.addListener(f2 -> finished.setSuccess()); + } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE + finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new FailureException("Response received from remote site was: " + response.status()); } } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 57b4bc2f575..3fb8c187ad9 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -19,40 +5,20 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -import java.util.Arrays; -import javax.inject.Inject; -/** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. - * - *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a {@code - * name} method, which returns a standard name and the current hostname.

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - @Inject - public HttpRequestMessage() { - this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, - ByteBuf content) { + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } - /** - * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} - */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } @Override public HttpRequestMessage setUri(String path) { @@ -60,30 +26,15 @@ public HttpRequestMessage setUri(String path) { return this; } - /** - * Modifies headers to reflect new host and new path if applicable. - */ - @Override - public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { - if (args.length == 1 || args.length == 2) { - headers().set("host", args[0]); - if (args.length == 2) { - setUri(args[1]); - } - - return this; + public static HttpRequestMessage fromRequest(FullHttpRequest request) { + ByteBuf buf = request.content(); + if (buf == null) { + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); } else { - throw new IllegalArgumentException( - String.format( - "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + Arrays.toString(args), args.length)); + return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); } - } - @Override - public String toString() { - return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index c3f173729e9..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,9 +6,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} - */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -33,12 +16,23 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - /** - * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} - */ - public HttpResponseMessage(FullHttpResponse response) { - this(response.protocolVersion(), response.status(), response.content()); - response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + public static HttpResponseMessage fromResponse(FullHttpResponse response) { + HttpResponseMessage finalResponse; + ByteBuf buf = response.content(); + + if (buf == null) + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); + else + finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); + + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); + + return finalResponse; } + + + } diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index e8c200b08e2..d5d56469b36 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index c0fbdae28b3..95b449dbc89 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index c6232d847b4..440e4908417 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 8e98ee5fc70..1b923b7eae3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// Copyright 2019 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. From d9165af42ba831c1788d1bdcbcb028c191cf3491 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 2 Jul 2019 10:58:52 -0400 Subject: [PATCH 303/337] Fixed changes suggested by CydeWeys --- prober/build.gradle | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/prober/build.gradle b/prober/build.gradle index e1e1e1144b3..ae4bd27b731 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,10 +16,13 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - + compile deps['com.google.auto.value:auto-value-annotations'] + compile deps['com.google.code.findbugs:jsr305'] + compile deps['com.google.code.gson:gson'] compile deps['com.google.dagger:dagger'] compile deps['com.google.flogger:flogger'] compile deps['com.google.guava:guava'] @@ -31,11 +34,13 @@ dependencies { compile deps['io.netty:netty-transport'] compile deps['javax.inject:javax.inject'] compile deps['joda-time:joda-time'] + compile deps['org.bouncycastle:bcpkix-jdk15on'] + compile deps['org.bouncycastle:bcprov-jdk15on'] runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - + testCompile deps['com.google.truth:truth'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] @@ -48,3 +53,4 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } + From d9b225f466473fec276c9cda240181d5c44797b7 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:06:28 -0400 Subject: [PATCH 304/337] Added missing license headers and JavaDoc --- .../handlers/ServerSideException.java | 16 ++++++- .../blackbox/messages/HttpRequestMessage.java | 45 ++++++++++++++----- .../messages/HttpResponseMessage.java | 32 ++++++++++--- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java index 5d3addb920e..441062a9e7b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; /** @@ -12,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 3fb8c187ad9..8fbb55c6339 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,13 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} + * (but needs to implement {@link OutboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion + * from {@link FullHttpRequest} to its type

+ */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +35,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,15 +42,22 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - if (buf == null) { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - return new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //creates message based on content found in original request + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } + //stores headers from request in finalRequest + request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); + + return finalRequest; + + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..776e7de0824 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,11 +1,33 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} + * (but needs to implement {@link InboundMessageType}) + * + *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion + * from {@link FullHttpResponse} to its type

+ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -17,22 +39,20 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } + /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); + //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + //stores headers from response in finalResponse + response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); return finalResponse; } - - - } From 6deeaa0350cc9a035219920eddb65bd439c3463d Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 12:11:25 -0400 Subject: [PATCH 305/337] Minor fix in NewChannelAction JavaDoc --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 0ba3a0c22be..1e7578d5679 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,7 +14,6 @@ package google.registry.monitoring.blackbox; - import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -28,8 +27,7 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel + * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) */ @AutoValue public abstract class NewChannelAction extends ProbingAction { From c41a60eb42066dfab4ea8082d5559eb42e98aade Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 17 Jul 2019 13:33:23 -0400 Subject: [PATCH 306/337] Minor Style Fix --- .../google/registry/monitoring/blackbox/NewChannelAction.java | 4 ---- .../monitoring/blackbox/handlers/WebWhoisActionHandler.java | 2 -- 2 files changed, 6 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 1e7578d5679..84cf75492f2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -52,7 +52,6 @@ public Channel channel() { return this.channel; } - @Override public abstract Builder toBuilder(); @@ -120,7 +119,6 @@ public static NewChannelAction.Builder builder() return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); } - @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -129,6 +127,4 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 21010f0e887..5b77461cd8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -131,7 +131,5 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } } - - } From 4ebefa13d875ec903733c65ff04e87abaf9e08d6 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 12:40:37 -0400 Subject: [PATCH 307/337] Full WebWhoIs Sequence Added --- prober/build.gradle | 10 +- .../blackbox/ExistingChannelAction.java | 48 ++++ .../monitoring/blackbox/NewChannelAction.java | 17 +- .../registry/monitoring/blackbox/Prober.java | 23 +- .../monitoring/blackbox/ProbingAction.java | 17 +- .../monitoring/blackbox/ProbingStepWeb.java | 45 ++++ .../monitoring/blackbox/Protocol.java | 1 + .../monitoring/blackbox/TokenModule.java | 37 +++ .../monitoring/blackbox/Tokens/Token.java | 45 ++++ .../blackbox/Tokens/WebWhoisToken.java | 57 +++++ .../exceptions/EppClientException.java | 29 +++ .../exceptions/InternalException.java | 29 +++ .../exceptions/ResponseException.java | 29 +++ .../ServerSideException.java | 4 +- .../blackbox/handlers/MessageHandler.java | 6 + .../handlers/WebWhoisActionHandler.java | 19 +- .../blackbox/messages/HttpRequestMessage.java | 50 ++-- .../messages/HttpResponseMessage.java | 32 +-- .../blackbox/ProbingSequenceStepTest.java | 219 ++++++++++++++++++ .../monitoring/blackbox/TokenTest.java | 60 +++++ .../blackbox/handlers/ConversionHandler.java | 11 +- .../blackbox/handlers/TestActionHandler.java | 15 +- 22 files changed, 700 insertions(+), 103 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java rename prober/src/main/java/google/registry/monitoring/blackbox/{handlers => exceptions}/ServerSideException.java (94%) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java create mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/build.gradle b/prober/build.gradle index ae4bd27b731..b23314728e1 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -17,9 +17,10 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') + dependencies { def deps = rootProject.dependencyMap - + compile deps['com.google.auto.value:auto-value-annotations'] compile deps['com.google.code.findbugs:jsr305'] compile deps['com.google.code.gson:gson'] @@ -40,11 +41,12 @@ dependencies { runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] runtime deps['io.netty:netty-tcnative-boringssl-static'] - + testCompile deps['com.google.truth:truth'] testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') + //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -54,3 +56,7 @@ dependencies { testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } +task(runMain, dependsOn: 'classes', type: JavaExec) { + main = 'google.registry.monitoring.blackbox.Prober' + classpath = sourceSets.main.runtimeClasspath +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java new file mode 100644 index 00000000000..a9c93804da6 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -0,0 +1,48 @@ +// Copyright 2019 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.monitoring.blackbox; + +import com.google.auto.value.AutoValue; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + +/** + * Subclass of {@link ProbingAction} that takes in an existing channel + */ +@AutoValue +public abstract class ExistingChannelAction extends ProbingAction { + + public static ExistingChannelAction.Builder builder() { + return new AutoValue_ExistingChannelAction.Builder().path(""); + } + + @Override + public abstract Builder toBuilder(); + + @Override + public ChannelFuture call() { + //only thing necessary is reset the PROBING_ACTION_KEY of + //the channel to reflect the current ProbingAction + channel().attr(PROBING_ACTION_KEY).set(this); + return super.call(); + } + + @AutoValue.Builder + public static abstract class Builder extends ProbingAction.Builder { + //specifies channel in this builder + public abstract Builder channel(Channel channel); + } +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java index 84cf75492f2..56939e525e1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java @@ -14,6 +14,9 @@ package google.registry.monitoring.blackbox; + +import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; + import com.google.auto.value.AutoValue; import com.google.common.flogger.FluentLogger; import io.netty.bootstrap.Bootstrap; @@ -27,16 +30,14 @@ /** *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters * - * @param For testing Purposes to use different kinds of channels (other than {@link NioSocketChannel}) + * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) + * Subclass of ProbingAction where each instance creates a new channel */ @AutoValue public abstract class NewChannelAction extends ProbingAction { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** Default {@link LocalAddress} when not initialized in {@code Builder} */ - private final static LocalAddress DEFAULT_ADDRESS = new LocalAddress("TEST_ADDRESS"); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ public abstract LocalAddress address(); @@ -52,6 +53,7 @@ public Channel channel() { return this.channel; } + @Override public abstract Builder toBuilder(); @@ -83,7 +85,7 @@ protected void initChannel(C outboundChannel) ChannelFuture connectionFuture; - if (!host().equals("")) { + if (address() == DEFAULT_ADDRESS) { connectionFuture = bootstrap.connect(host(), protocol().port()); } else { connectionFuture = bootstrap.connect(address()); @@ -116,9 +118,10 @@ protected void initChannel(C outboundChannel) } public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path("").address(DEFAULT_ADDRESS); + return new AutoValue_NewChannelAction.Builder().path(""); } + @AutoValue.Builder public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { //specifies bootstrap in this builder @@ -127,4 +130,6 @@ public static abstract class Builder extends ProbingA public abstract NewChannelAction.Builder address(LocalAddress value); } + } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 333330207f1..69cc22142d2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,16 +15,31 @@ package google.registry.monitoring.blackbox; import com.google.common.collect.ImmutableMap; +import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import google.registry.monitoring.blackbox.Tokens.Token; +import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which constructs the ProbingSequences then runs them + * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them */ public class Prober { - //TODO: Create ImmutableMap between port numbers and protocols with Dagger - public static final ImmutableMap portToProtocolMap = ImmutableMap.of(); + /** Main {@link Dagger} Component */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + + /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ + public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); + - //TODO: Create and run probing sequences public static void main(String[] args) { + + ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); + Token httpsToken = proberComponent.provideWebWhoisToken(); + + ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); + Token httpToken = proberComponent.provideWebWhoisToken(); + httpsSequence.start(httpsToken); + httpSequence.start(httpToken); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 2441debb12d..6eaac944744 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -34,7 +34,7 @@ import javax.inject.Provider; /** - *Superclass that represents action generated by {@link ProbingStep} + * Superclass that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -183,4 +183,19 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + @Override + public String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n" + + "path: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host(), + path() + ); + } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java new file mode 100644 index 00000000000..255795d97e8 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.channel.AbstractChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; + +/** + * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow + * + * @param refer to {@code C} in {@link ProbingStep} + * + *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

+ */ +public class ProbingStepWeb extends ProbingStep{ + @Inject + public ProbingStepWeb(Protocol protocol) { + super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); + duration = DEFAULT_DURATION; + } + + @Override + Protocol protocol() { + return protocol; + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index d458e5cc4da..294a4a1b27a 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -87,3 +87,4 @@ public String toString() { ); } } + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java new file mode 100644 index 00000000000..ba656a38b87 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.monitoring.blackbox; + +import dagger.Module; +import dagger.Provides; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import javax.inject.Qualifier; + +@Module +public class TokenModule { + + @Qualifier + public @interface WebWhoIs {} + + @Provides + @WebWhoisProtocol + static Token provideToken(@WebWhoisProtocol String domainName) { + return new WebWhoisToken(domainName); + } + + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java new file mode 100644 index 00000000000..aa3a6c58959 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -0,0 +1,45 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.channel.Channel; + +/** + * Superclass that represents information passed to each {@link ProbingStep} + * a given loop in a {@link ProbingSequence}. + * + *

Should modify the message passed in to reflect the current host, should pass down + * a channel if a persistent connection exists in the sequence, and should be able to obtain + * the next Token when moving on to the next iteration of a loop in the sequence.

+ */ +public abstract class Token { + + protected Channel channel; + + public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) + throws InternalException; + public abstract String getHost(); + + public void channel(Channel channel) { + this.channel = channel; + } + public Channel channel() { + return this.channel; + } + +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java new file mode 100644 index 00000000000..03e12666313 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -0,0 +1,57 @@ +// Copyright 2019 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.monitoring.blackbox.Tokens; + +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; + + +/** + * {@link Token} subtype that deals performs specified actions for the WebWhois sequence + */ +public class WebWhoisToken extends Token { + private static final String PREFIX = "whois.nic."; + private String name; + private String host; + + /** Initialized via TLD name */ + public WebWhoisToken(String tld) { + name = tld; + host = PREFIX + name; + } + + /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ + @Override + public Token next() { + return new WebWhoisToken(name); + } + + /** Modifies the message to reflect the new host */ + @Override + public OutboundMessageType modifyMessage(OutboundMessageType original) { + HttpRequestMessage request = (HttpRequestMessage) original; + request.headers().set("host", host); + + return request; + } + + @Override + public String getHost() { + return host; + } + + +} + diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java new file mode 100644 index 00000000000..2ee2230de62 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class EppClientException extends InternalException { + + public EppClientException(String msg) { + super(msg); + } + + public EppClientException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java new file mode 100644 index 00000000000..6b6946c6731 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class InternalException extends Exception { + + public InternalException(String msg) { + super(msg); + } + + public InternalException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java new file mode 100644 index 00000000000..6116e77040b --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -0,0 +1,29 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Base exception class for all instances when the Status of the task performed is ERROR + */ +public class ResponseException extends Exception { + + public ResponseException(String msg) { + super(msg); + } + + public ResponseException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java similarity index 94% rename from prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java rename to prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 441062a9e7b..31196d776f4 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox.handlers; +package google.registry.monitoring.blackbox.exceptions; /** * Base exception class for all instances when the Status of the task performed is ERROR @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} +} \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java new file mode 100644 index 00000000000..ac18e5db0b1 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -0,0 +1,6 @@ +package google.registry.monitoring.blackbox.handlers; + +import io.netty.channel.ChannelDuplexHandler; + +public abstract class MessageHandler extends ChannelDuplexHandler { +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 5b77461cd8f..f16658a4f90 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -17,20 +17,16 @@ import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.NewChannelAction; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.ServerSideException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; @@ -59,7 +55,7 @@ public WebWhoisActionHandler() {} */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ServerSideException { + throws ResponseException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -67,9 +63,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - finished.setSuccess(); - logger.atInfo().log("Response Received: " + response); + super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -79,7 +74,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ServerSideException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -126,10 +121,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE - finished.setSuccess(); logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); + throw new ResponseException("Response received from remote site was: " + response.status()); } } + + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 8fbb55c6339..338847bb561 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,17 +1,3 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -20,13 +6,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link OutboundMessageType} instance which functions identically to {@link DefaultFullHttpRequest} - * (but needs to implement {@link OutboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpRequest} and allows for conversion - * from {@link FullHttpRequest} to its type

- */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -35,6 +14,11 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { + super(httpVersion, method, uri, content, validateHeaders); + } + + @Override public HttpRequestMessage setUri(String path) { @@ -42,22 +26,16 @@ public HttpRequestMessage setUri(String path) { return this; } - /** Converts from {@link FullHttpRequest} to type {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - - //creates message based on content found in original request - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - - - //stores headers from request in finalRequest - request.headers().forEach((pair) -> finalRequest.headers().set(pair.getKey(), pair.getValue())); - - return finalRequest; - + HttpRequestMessage output; + if (buf == null) { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + } else { + output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + } + request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); + return output; } + } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 776e7de0824..fa408ee9ffe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,33 +1,11 @@ -// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; -/** - * {@link InboundMessageType} instance which functions identically to {@link DefaultFullHttpResponse} - * (but needs to implement {@link InboundMessageType}) - * - *

Uses identical constructors to {@link DefaultFullHttpResponse} and allows for conversion - * from {@link FullHttpResponse} to its type

- */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -39,20 +17,22 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } - /** Converts from {@link FullHttpResponse} to type {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); - //creates message based on content found in original response if (buf == null) finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - //stores headers from response in finalResponse - response.headers().forEach((pair) -> finalResponse.headers().set(pair.getKey(), pair.getValue())); + + if (response.headers().get("location") != null) + finalResponse.headers().set("location", response.headers().get("location")); return finalResponse; } + + + } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java new file mode 100644 index 00000000000..7a713017072 --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java @@ -0,0 +1,219 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.JUnitBackports.assertThrows; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.TestUtils.DummyStep; +import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; +import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; +import google.registry.monitoring.blackbox.TestUtils.TestProvider; +import google.registry.monitoring.blackbox.TestUtils.TestStep; +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.handlers.ActionHandler; +import google.registry.monitoring.blackbox.handlers.ConversionHandler; +import google.registry.monitoring.blackbox.handlers.NettyRule; +import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultPromise; +import javax.inject.Provider; +import org.junit.Rule; +import org.junit.Test; + +/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ +public class ProbingSequenceStepTest { + + /** Basic Constants necessary for tests */ + private final String ADDRESS_NAME = "TEST_ADDRESS"; + private final String PROTOCOL_NAME = "TEST_PROTOCOL"; + private final int PROTOCOL_PORT = 0; + private final String TEST_MESSAGE = "TEST_MESSAGE"; + private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; + + private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); + private final LocalAddress address = new LocalAddress(ADDRESS_NAME); + + /** Used for testing how well probing step can create connection to blackbox server */ + @Rule + public NettyRule nettyRule = new NettyRule(eventLoopGroup); + + + /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ + private ActionHandler testHandler = new TestActionHandler(); + private ChannelHandler conversionHandler = new ConversionHandler(); + + /** Wrapper provider classes of these handlers */ + private Provider testHandlerProvider = new TestProvider<>(testHandler); + private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); + + /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ + private EmbeddedChannel channel; + private Protocol testProtocol; + + + + /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ + private ProbingStep firstStep; + private ProbingStep dummyStep; + + /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ + private ProbingSequence testSequence; + + /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ + private Token testToken; + + /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ + private void setupNewChannelToken() { + testToken = new NewChannelToken(""); + } + + /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ + private void setupExistingChannelToken() { + testToken = new ExistingChannelToken(channel, ""); + } + + /** Sets up an embedded channel to contain the two handlers we created already */ + private void setupChannel() { + channel = new EmbeddedChannel(conversionHandler, testHandler); + } + + /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ + private void setupSteps() { + firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); + dummyStep = new DummyStep(testProtocol, eventLoopGroup); + } + + /** Sets up testProtocol for when we create a new channel */ + private void setupNewProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(false) + .build(); + } + + /** Sets up testProtocol for when a channel already exists */ + private void setupExistingProtocol() { + testProtocol = Protocol.builder() + .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .name(PROTOCOL_NAME) + .port(PROTOCOL_PORT) + .persistentConnection(true) + .build(); + } + + /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ + private void setupSequence() { + testSequence = new ProbingSequence.Builder() + .eventLoopGroup(eventLoopGroup) + .setClass(LocalChannel.class) + .addStep(firstStep) + .makeFirstRepeated() + .addStep(dummyStep) + .build(); + } + + + @Test + public void testGeneralBehavior() { + //setup + setupNewProtocol(); + setupSteps(); + setupNewChannelToken(); + + //there should be no next step + assertThat(firstStep.nextStep()).isNull(); + + //we expect that this exception be thrown + assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); + + } + + @Test + public void testWithSequence_NewChannel() throws Exception { + //setup + setupNewProtocol(); + setupSteps(); + setupSequence(); + setupNewChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Set up blackbox server that recieves our messages then echoes them back to us + nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + + //Call accept on the first step, which should send our message to the server, which will then be + //echoed back to us, causing us to move to the next step + firstStep.accept(testToken); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //checks that we have appropriately sent the write message to server + nettyRule.assertThatCustomWorks(TEST_MESSAGE); + + //checks that when the future is successful, we pass down the requisite token + assertThat(future.get()).isEqualTo(testToken); + + } + + @Test + public void testWithSequence_ExistingChannel() throws Exception { + //setup + setupExistingProtocol(); + setupSteps(); + setupSequence(); + setupChannel(); + setupExistingChannelToken(); + + //checks that the ProbingSteps are appropriately pointing to each other + assertThat(firstStep.nextStep()).isEqualTo(dummyStep); + assertThat(dummyStep.nextStep()).isEqualTo(firstStep); + + //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline + firstStep.accept(testToken); + + //Ensures the accurate message is sent down the pipeline + assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); + + //Obtains future for when we have moved to the next step + DefaultPromise future = ((DummyStep)dummyStep).getFuture(); + + //Write response to our message down EmbeddedChannel pipeline + channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); + + //At this point, we should have received the message, so the future obtained should be marked as a success + assertThat(future.isSuccess()); + + //checks that the requisite token is passed down + assertThat(future.get()).isEqualTo(testToken); + + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java new file mode 100644 index 00000000000..ef5cba5b60d --- /dev/null +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -0,0 +1,60 @@ +// Copyright 2019 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.monitoring.blackbox; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.monitoring.blackbox.Tokens.Token; +import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + */ +@RunWith(JUnit4.class) +public class TokenTest { + + private static String PREFIX = "whois.nic."; + private static String TEST_STARTER = "starter"; + private static String TEST_DOMAIN = "test"; + + public Token webToken = new WebWhoisToken(TEST_DOMAIN); + + @Test + public void testWebToken_MessageModificationSuccess() { + //creates Request message with header + HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + message.headers().set("host", TEST_STARTER); + + //attempts to use Token's method for modifying the method based on its stored host + try { + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + } catch(InternalException e) { + throw new RuntimeException(e); + } + + + + + } + +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index c9d337d6ad8..b5363aa8139 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,13 +17,10 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.messages.TestMessage; +import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -31,8 +28,8 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); + super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 19e608c97d2..3357f14f6c5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,7 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.FailureException; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -23,18 +22,18 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from parent class * other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler { +public class TestActionHandler extends ActionHandler{ - private InboundMessageType receivedMessage; + private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage; + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } - public InboundMessageType getResponse() { + @Override + public String toString() { return receivedMessage; } From 457d126037b7a43253ef2ad63ea33dd99388e0ed Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 18 Jul 2019 16:00:25 -0400 Subject: [PATCH 308/337] fixed build issues --- .../blackbox/ExistingChannelAction.java | 1 - .../monitoring/blackbox/NewChannelAction.java | 31 +++++++++----- .../registry/monitoring/blackbox/Prober.java | 1 - .../monitoring/blackbox/Protocol.java | 1 - .../monitoring/blackbox/TokenModule.java | 2 - .../monitoring/blackbox/Tokens/Token.java | 4 +- .../blackbox/Tokens/WebWhoisToken.java | 3 -- .../exceptions/EppClientException.java | 29 ------------- .../exceptions/ServerSideException.java | 2 +- .../blackbox/handlers/MessageHandler.java | 22 +++++++++- .../blackbox/messages/HttpRequestMessage.java | 41 +++++++++++++------ .../messages/HttpResponseMessage.java | 26 ++++++++---- 12 files changed, 91 insertions(+), 72 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java index a9c93804da6..1f656020ea6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java @@ -45,4 +45,3 @@ public static abstract class Builder extends ProbingAction.Builder extends Probin private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link LocalAddress} for connection. ONLY FOR TESTING*/ + /** + * {@link LocalAddress} for connection. ONLY FOR TESTING + */ public abstract LocalAddress address(); - /** {@link Channel} created from bootstrap connection to protocol's specified host and port*/ + /** + * {@link Channel} created from bootstrap connection to protocol's specified host and port + */ private Channel channel; - /** {@link Bootstrap} object associated with this {@link ProbingAction} */ + /** + * {@link Bootstrap} object associated with this {@link ProbingAction} + */ abstract Bootstrap bootstrap(); - /** {@link Channel} object instantiated in {@code call()} */ + /** + * {@link Channel} object instantiated in {@code call()} + */ @Override public Channel channel() { return this.channel; @@ -60,8 +68,8 @@ public Channel channel() { /** * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance * - * @return ChannelFuture instance that is set to success when previous action has - * finished and requisite time as passed + * @return ChannelFuture instance that is set to success when previous action has finished and + * requisite time as passed */ @Override public ChannelFuture call() { @@ -79,7 +87,6 @@ protected void initChannel(C outboundChannel) }) .attr(PROBING_ACTION_KEY, this); - logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established @@ -101,7 +108,9 @@ protected void initChannel(C outboundChannel) connectionFuture.addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { - logger.atInfo().log(String.format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); ChannelFuture future = super.call(); future.addListener(f -> finished.setSuccess()); @@ -123,13 +132,13 @@ public static NewChannelAction.Builder builder() @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder, NewChannelAction> { + public static abstract class Builder extends + ProbingAction.Builder, NewChannelAction> { + //specifies bootstrap in this builder public abstract NewChannelAction.Builder bootstrap(Bootstrap value); public abstract NewChannelAction.Builder address(LocalAddress value); } - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 69cc22142d2..6e0b17d2799 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -42,4 +42,3 @@ public static void main(String[] args) { httpSequence.start(httpToken); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index 294a4a1b27a..d458e5cc4da 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -87,4 +87,3 @@ public String toString() { ); } } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java index ba656a38b87..c058ff23e5e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java @@ -32,6 +32,4 @@ public class TokenModule { static Token provideToken(@WebWhoisProtocol String domainName) { return new WebWhoisToken(domainName); } - - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java index aa3a6c58959..e96941a506c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java @@ -31,15 +31,17 @@ public abstract class Token { protected Channel channel; public abstract Token next(); + public abstract OutboundMessageType modifyMessage(OutboundMessageType message) throws InternalException; + public abstract String getHost(); public void channel(Channel channel) { this.channel = channel; } + public Channel channel() { return this.channel; } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java index 03e12666313..5f03faeee8c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java @@ -51,7 +51,4 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) { public String getHost() { return host; } - - } - diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java deleted file mode 100644 index 2ee2230de62..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/EppClientException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class EppClientException extends InternalException { - - public EppClientException(String msg) { - super(msg); - } - - public EppClientException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java index 31196d776f4..fd3320b1495 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java @@ -26,4 +26,4 @@ public ServerSideException(String msg) { public ServerSideException(Throwable e) { super(e); } -} \ No newline at end of file +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java index ac18e5db0b1..90e4e607b02 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java @@ -1,6 +1,24 @@ +// Copyright 2019 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.monitoring.blackbox.handlers; import io.netty.channel.ChannelDuplexHandler; -public abstract class MessageHandler extends ChannelDuplexHandler { -} +/** + * Abstract class whose subclasses handle the {@link InboundMessageType} and + * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} + * + */ +public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 338847bb561..b06938d80a1 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + */ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { @@ -14,11 +31,6 @@ public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, content, validateHeaders); - } - - @Override public HttpRequestMessage setUri(String path) { @@ -26,16 +38,19 @@ public HttpRequestMessage setUri(String path) { return this; } + /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ public static HttpRequestMessage fromRequest(FullHttpRequest request) { + HttpRequestMessage finalRequest; ByteBuf buf = request.content(); - HttpRequestMessage output; - if (buf == null) { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - } else { - output = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); - } - request.headers().forEach((entry) -> output.headers().set(entry.getKey(), entry.getValue())); - return output; + + if (buf == null) + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); + else + finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + + request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + + return finalRequest; } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index fa408ee9ffe..283b14440ac 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.monitoring.blackbox.messages; import io.netty.buffer.ByteBuf; @@ -6,6 +20,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; +/** + * {@link InboundMessageType} subtype that acts identically to {@link DefaultFullHttpResponse} + */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { @@ -16,7 +33,7 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB super(version, status, content); } - + /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ public static HttpResponseMessage fromResponse(FullHttpResponse response) { HttpResponseMessage finalResponse; ByteBuf buf = response.content(); @@ -26,13 +43,8 @@ public static HttpResponseMessage fromResponse(FullHttpResponse response) { else finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - if (response.headers().get("location") != null) - finalResponse.headers().set("location", response.headers().get("location")); + response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); return finalResponse; } - - - } From 411407cee08e09feaf5c6dad0be462f542ec5f4c Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 26 Jul 2019 17:37:43 -0400 Subject: [PATCH 309/337] Refactored by responses suggested by jianglai. --- .../blackbox/ExistingChannelAction.java | 47 --- .../monitoring/blackbox/NewChannelAction.java | 144 --------- .../registry/monitoring/blackbox/Prober.java | 20 +- .../monitoring/blackbox/ProbingAction.java | 275 ++++++++++++------ .../monitoring/blackbox/ProbingStepWeb.java | 45 --- .../monitoring/blackbox/TokenModule.java | 35 --- .../monitoring/blackbox/Tokens/Token.java | 47 --- .../blackbox/Tokens/WebWhoisToken.java | 54 ---- .../exceptions/InternalException.java | 3 +- .../exceptions/ResponseException.java | 2 +- .../exceptions/ServerSideException.java | 29 -- .../blackbox/handlers/MessageHandler.java | 24 -- .../handlers/SslClientInitializer.java | 9 +- .../handlers/WebWhoisActionHandler.java | 102 +++++-- .../blackbox/messages/HttpRequestMessage.java | 46 ++- .../messages/HttpResponseMessage.java | 14 +- .../blackbox/modules/secrets/epp_host.txt | 1 + .../modules/secrets/keystore_password.txt | 1 + .../blackbox/modules/secrets/password.txt | 1 + .../secrets/prober-client-tls-sandbox.p12 | Bin 0 -> 1717 bytes .../blackbox/modules/secrets/user_id.txt | 1 + 21 files changed, 322 insertions(+), 578 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 create mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java deleted file mode 100644 index 1f656020ea6..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ExistingChannelAction.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import com.google.auto.value.AutoValue; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -/** - * Subclass of {@link ProbingAction} that takes in an existing channel - */ -@AutoValue -public abstract class ExistingChannelAction extends ProbingAction { - - public static ExistingChannelAction.Builder builder() { - return new AutoValue_ExistingChannelAction.Builder().path(""); - } - - @Override - public abstract Builder toBuilder(); - - @Override - public ChannelFuture call() { - //only thing necessary is reset the PROBING_ACTION_KEY of - //the channel to reflect the current ProbingAction - channel().attr(PROBING_ACTION_KEY).set(this); - return super.call(); - } - - @AutoValue.Builder - public static abstract class Builder extends ProbingAction.Builder { - //specifies channel in this builder - public abstract Builder channel(Channel channel); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java deleted file mode 100644 index 749a647cc68..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/NewChannelAction.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - - -import static google.registry.monitoring.blackbox.ProbingStep.DEFAULT_ADDRESS; - -import com.google.auto.value.AutoValue; -import com.google.common.flogger.FluentLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.AbstractChannel; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPromise; -import io.netty.channel.local.LocalAddress; - -/** - *Subclass of {@link ProbingAction} that creates a new {@link Channel} based on its parameters - * - * @param For testing Purposes to use different kinds of channels (other than NioSocketChannel) - * Subclass of ProbingAction where each instance creates a new channel - */ -@AutoValue -public abstract class NewChannelAction extends ProbingAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - /** - * {@link LocalAddress} for connection. ONLY FOR TESTING - */ - public abstract LocalAddress address(); - - /** - * {@link Channel} created from bootstrap connection to protocol's specified host and port - */ - private Channel channel; - - /** - * {@link Bootstrap} object associated with this {@link ProbingAction} - */ - abstract Bootstrap bootstrap(); - - /** - * {@link Channel} object instantiated in {@code call()} - */ - @Override - public Channel channel() { - return this.channel; - } - - - @Override - public abstract Builder toBuilder(); - - /** - * Creates channel from {@link Bootstrap} and {@link Bootstrap} given to instance - * - * @return ChannelFuture instance that is set to success when previous action has finished and - * requisite time as passed - */ - @Override - public ChannelFuture call() { - - //Calls on bootstrap method - Bootstrap bootstrap = bootstrap(); - bootstrap.handler( - new ChannelInitializer() { - @Override - protected void initChannel(C outboundChannel) - throws Exception { - //Uses Handlers from Protocol to fill pipeline - addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); - } - }) - .attr(PROBING_ACTION_KEY, this); - - logger.atInfo().log("Initialized bootstrap with channel Handlers"); - //ChannelFuture that performs action when connection is established - - ChannelFuture connectionFuture; - - if (address() == DEFAULT_ADDRESS) { - connectionFuture = bootstrap.connect(host(), protocol().port()); - } else { - connectionFuture = bootstrap.connect(address()); - } - - //ChannelPromise that we return - ChannelPromise finished = connectionFuture.channel().newPromise(); - - //set current channel to one associated with connectionFuture - this.channel = connectionFuture.channel(); - - //When connection is established call super.call and set returned listener to success - connectionFuture.addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { - logger.atInfo().log(String - .format("Successful connection to remote host: %s at port: %d", host(), - protocol().port())); - ChannelFuture future = super.call(); - future.addListener(f -> finished.setSuccess()); - - } else { - //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( - "Cannot connect to relay channel for %s channel: %s.", - protocol().name(), this.channel()); - ChannelFuture unusedFuture = channel().close(); - } - } - ); - return finished; - } - - public static NewChannelAction.Builder builder() { - return new AutoValue_NewChannelAction.Builder().path(""); - } - - - @AutoValue.Builder - public static abstract class Builder extends - ProbingAction.Builder, NewChannelAction> { - - //specifies bootstrap in this builder - public abstract NewChannelAction.Builder bootstrap(Bootstrap value); - - public abstract NewChannelAction.Builder address(LocalAddress value); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 6e0b17d2799..b9a89a9382b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,31 +14,23 @@ package google.registry.monitoring.blackbox; -import com.google.common.collect.ImmutableMap; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import google.registry.monitoring.blackbox.Tokens.Token; -import io.netty.channel.socket.nio.NioSocketChannel; /** - * Main class of the Prober, which obtains the {@link ProbingSequences}s provided by {@link Dagger} and runs them + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. */ public class Prober { - /** Main {@link Dagger} Component */ + /** Main Dagger Component */ private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); - /** {@link ImmutableMap} of {@code port}s to {@link Protocol}s for WebWhois Redirects */ - public static final ImmutableMap portToProtocolMap = proberComponent.providePortToProtocolMap(); - public static void main(String[] args) { - ProbingSequence httpsSequence = proberComponent.provideHttpsWhoisSequence(); - Token httpsToken = proberComponent.provideWebWhoisToken(); + //Obtains WebWhois Sequence provided by proberComponent + ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); - ProbingSequence httpSequence = proberComponent.provideHttpWhoisSequence(); - Token httpToken = proberComponent.provideWebWhoisToken(); - httpsSequence.start(httpsToken); - httpSequence.start(httpToken); + //Tells Sequence to start running + webWhoisSequence.start(); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 6eaac944744..7f7aa801f6e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -15,12 +15,22 @@ package google.registry.monitoring.blackbox; import static com.google.common.flogger.StackSize.SMALL; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInitializer; import io.netty.util.AttributeKey; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.joda.time.Duration; import io.netty.channel.Channel; @@ -34,7 +44,7 @@ import javax.inject.Provider; /** - * Superclass that represents action generated by {@link ProbingStep} + * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the @@ -44,36 +54,22 @@ * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} * gives the outline and {@link ProbingAction} gives the details of that connection.

* - *

There are two main subclasses. {@link NewChannelAction} creates a new channel based on the {@link Protocol} and - * details specified for itself. {@link ExistingChannelAction} simply takes in an existing channel. Then both send - * {@link OutboundMessageType} instance specified down the pipeline in the channel.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. + * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. + * If the channel is supplied, the connection future is automatically set to successful.

*/ - +@AutoValue public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - /** {@link AttributeKey} that specifies which {@link ProbingAction} is associated with the {@link Channel} in question*/ - public final static AttributeKey PROBING_ACTION_KEY = AttributeKey.valueOf("PROBING_ACTION_KEY"); - - - /** - * The {@link ActionHandler} associated with this {@link ProbingAction}, which is always the - * last {@link ChannelHandler} in the pipeline - * */ - private ActionHandler actionHandler; - - - /** Return of {@link ActionHandler}, which is always the last {@link ChannelHandler} in the pipeline */ - private ActionHandler actionHandler() { - return actionHandler; - } + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); /** {@link Timer} that rate limits probing */ private static final Timer timer = new HashedWheelTimer(); - /** Actual {@link Duration} of this delay */ public abstract Duration delay(); @@ -83,90 +79,202 @@ private ActionHandler actionHandler() { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); + /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ + public abstract ChannelFuture connectionFuture(); + /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); + /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - public abstract String path(); - - public abstract , P extends ProbingAction> Builder toBuilder(); - - - /** Performs the action specified by the ProbingAction and sets the ChannelPromise specified to a success */ - private void informListeners(ChannelPromise finished) { - ChannelFuture channelFuture = actionHandler().getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - future -> finished.setSuccess(), - future -> { - if (!protocol().persistentConnection()) { - - //If we created a new channel for this action, close the connection to the channel - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } + /** The {@link SocketAddress} instance that specifies remote address of connection */ + public abstract SocketAddress address(); + + /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ + public abstract Optional bootstrap(); + /** - * The method that sends the {@code outboundMessage} down the channel pipeline + * The method that performs the work of the actual action. * - * @return future that denotes when the action has been successfully performed + *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. + * From that, we can obtain a future that is marked as a success when we receive an expected + * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, + * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ * + * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + public ChannelFuture performAction() throws InternalException { + Iterator> handlerIterator = channel().pipeline().iterator(); + ActionHandler actionHandler = null; + + //Finds the ActionHandler from the pipeline and initializes it. + while (handlerIterator.hasNext()) { + ChannelHandler currentHandler = handlerIterator.next().getValue(); + if (currentHandler instanceof ActionHandler) { + actionHandler = (ActionHandler) currentHandler; + break; + } + } - @Override - public ChannelFuture call() { - - //Sets Action Handler to appropriately the last channel in the pipeline - //Logs severe if the last channel in the pipeline is not - try { - this.actionHandler = (ActionHandler) this.channel().pipeline().last(); - } catch (ClassCastException exception) { - logger.atSevere().withStackTrace(SMALL).log("Last Handler in the ChannelPipeline is not an ActionHandler"); + //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + if (actionHandler == null) { + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new InternalException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. ChannelPromise finished = channel().newPromise(); + //Necessary for use of actionHandler in lambda expression + ActionHandler finalActionHandler = actionHandler; + //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (!delay().equals(Duration.ZERO)) { - timer.newTimeout(timeout -> { - // Write appropriate message to pipeline - informListeners(finished); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); - } else { - //if no delay, just perform the next action, and inform ProbingStep when finished - informListeners(finished); - } + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = finalActionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> finalActionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); return finished; } - public abstract static class Builder, P extends ProbingAction> { + /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + @Override + public ChannelFuture call() throws InternalException { + //ChannelPromise that we return + ChannelPromise finished = channel().newPromise(); - public abstract B delay(Duration value); + //When connection is established call super.call and set returned listener to success + connectionFuture().addListener( + (ChannelFuture channelFuture) -> { + if (channelFuture.isSuccess()) { + logger.atInfo().log(String + .format("Successful connection to remote host: %s at port: %d", host(), + protocol().port())); + ChannelFuture future = performAction(); + future.addListener(f -> finished.setSuccess()); + + } else { + //if we receive a failure, log the failure, and close the channel + logger.atSevere().withCause(channelFuture.cause()).log( + "Cannot connect to relay channel for %s channel: %s.", + protocol().name(), this.channel()); + ChannelFuture unusedFuture = channel().close(); + } + } + ); + return finished; + } + + + /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setDelay(Duration value); + + public abstract Builder setOutboundMessage(OutboundMessageType value); + + public abstract Builder setProtocol(Protocol value); + + public abstract Builder setHost(String value); + + public abstract Builder setChannel(Channel channel); + + public abstract Builder setAddress(SocketAddress address); + + public abstract Builder setBootstrap(Bootstrap value); + + public abstract Builder setBootstrap(Optional value); + + public abstract Builder setConnectionFuture(ChannelFuture future); + + abstract Protocol protocol(); - public abstract B outboundMessage(OutboundMessageType value); + abstract Channel channel(); - public abstract B protocol(Protocol value); + abstract Optional address(); - public abstract B host(String value); + abstract Optional bootstrap(); - public abstract B path(String value); + abstract String host(); - public abstract P build(); + abstract ProbingAction autoBuild(); + public ProbingAction build() { + if (!address().isPresent()) + //If no address has been supplied, we set it based on the host and port + setAddress(new InetSocketAddress(host(), protocol().port())); + + if (protocol().persistentConnection() && channel() != null) { + //if a channel exists and we want to use it then we don't try to create one + setConnectionFuture(channel().newSucceededFuture()); + } else { + //otherwise, we must have a bootstrap present + assert(bootstrap().isPresent()); + + + bootstrap().get().handler( + new ChannelInitializer() { + @Override + protected void initChannel(Channel outboundChannel) + throws Exception { + //Uses Handlers from Protocol to fill pipeline + addHandlers(outboundChannel.pipeline(), protocol().handlerProviders()); + } + }) + .attr(PROTOCOL_KEY, protocol()) + .attr(REMOTE_ADDRESS_KEY, host()); + + logger.atInfo().log("Initialized bootstrap with channel Handlers"); + //ChannelFuture that performs action when connection is established + ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + + setChannel(connectionFuture.channel()); + setConnectionFuture(connectionFuture); + + } + //we don't want to actually store Bootstrap, so set its value to Optional.empty() + setBootstrap(Optional.empty()); + + //now we can actually build the ProbingAction + return autoBuild(); + } + } + + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); } /** @@ -183,19 +291,20 @@ static void addHandlers( channelPipeline.addLast(handlerProvider.get()); } } + + + @Override public String toString() { return String.format( "ProbingAction with delay: %d\n" + "outboundMessage: %s\n" + "protocol: %s\n" + - "host: %s\n" + - "path: %s\n", + "host: %s\n", delay().getStandardSeconds(), outboundMessage(), protocol(), - host(), - path() + host() ); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java deleted file mode 100644 index 255795d97e8..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStepWeb.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import io.netty.channel.AbstractChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpVersion; -import javax.inject.Inject; - -/** - * {@link ProbingStep} subclass that deals with setps in the WebWhoisFlow - * - * @param refer to {@code C} in {@link ProbingStep} - * - *

Only passes in requisite {@link Protocol} and {@link OutboundMessageType} to parent constructor

- */ -public class ProbingStepWeb extends ProbingStep{ - @Inject - public ProbingStepWeb(Protocol protocol) { - super(protocol, new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, "")); - duration = DEFAULT_DURATION; - } - - @Override - Protocol protocol() { - return protocol; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java deleted file mode 100644 index c058ff23e5e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TokenModule.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import dagger.Module; -import dagger.Provides; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; -import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import javax.inject.Qualifier; - -@Module -public class TokenModule { - - @Qualifier - public @interface WebWhoIs {} - - @Provides - @WebWhoisProtocol - static Token provideToken(@WebWhoisProtocol String domainName) { - return new WebWhoisToken(domainName); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java deleted file mode 100644 index e96941a506c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/Token.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import io.netty.channel.Channel; - -/** - * Superclass that represents information passed to each {@link ProbingStep} - * a given loop in a {@link ProbingSequence}. - * - *

Should modify the message passed in to reflect the current host, should pass down - * a channel if a persistent connection exists in the sequence, and should be able to obtain - * the next Token when moving on to the next iteration of a loop in the sequence.

- */ -public abstract class Token { - - protected Channel channel; - - public abstract Token next(); - - public abstract OutboundMessageType modifyMessage(OutboundMessageType message) - throws InternalException; - - public abstract String getHost(); - - public void channel(Channel channel) { - this.channel = channel; - } - - public Channel channel() { - return this.channel; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java deleted file mode 100644 index 5f03faeee8c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Tokens/WebWhoisToken.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.Tokens; - -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; - - -/** - * {@link Token} subtype that deals performs specified actions for the WebWhois sequence - */ -public class WebWhoisToken extends Token { - private static final String PREFIX = "whois.nic."; - private String name; - private String host; - - /** Initialized via TLD name */ - public WebWhoisToken(String tld) { - name = tld; - host = PREFIX + name; - } - - /**TODO: sequentially get each TLD in order and on each call to next, pass in next one in the sequence*/ - @Override - public Token next() { - return new WebWhoisToken(name); - } - - /** Modifies the message to reflect the new host */ - @Override - public OutboundMessageType modifyMessage(OutboundMessageType original) { - HttpRequestMessage request = (HttpRequestMessage) original; - request.headers().set("host", host); - - return request; - } - - @Override - public String getHost() { - return host; - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java index 6b6946c6731..e676333489e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the action performed fails + * due to the fault of the Prober. */ public class InternalException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java index 6116e77040b..d1028018602 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java @@ -15,7 +15,7 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the Status of the task performed is ERROR + * Base exception class for all instances when the status of the action performed is FAILURE. */ public class ResponseException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java deleted file mode 100644 index fd3320b1495..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ServerSideException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the Status of the task performed is ERROR - */ -public class ServerSideException extends Exception { - - public ServerSideException(String msg) { - super(msg); - } - - public ServerSideException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java deleted file mode 100644 index 90e4e607b02..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/MessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.handlers; - -import io.netty.channel.ChannelDuplexHandler; - -/** - * Abstract class whose subclasses handle the {@link InboundMessageType} and - * {@link OutboundMessageType} being passed to and from the {@link ActionHandler} - * - */ -public abstract class MessageHandler extends ChannelDuplexHandler {} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java index 9913f948944..c62668b19b2 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/SslClientInitializer.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.handlers; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.ProbingAction.REMOTE_ADDRESS_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.flogger.FluentLogger; @@ -88,8 +89,8 @@ private SslClientInitializer( @Override protected void initChannel(C channel) throws Exception { - ProbingAction action = channel.attr(PROBING_ACTION_KEY).get(); - Protocol protocol = action.protocol(); + Protocol protocol = channel.attr(PROTOCOL_KEY).get(); + String host = channel.attr(REMOTE_ADDRESS_KEY).get(); //Builds SslHandler from Protocol, and based on if we require a privateKey and certificate checkNotNull(protocol, "Protocol is not set for channel: %s", channel); @@ -104,7 +105,7 @@ protected void initChannel(C channel) throws Exception { SslHandler sslHandler = sslContextBuilder .build() - .newHandler(channel.alloc(), action.host(), protocol.port()); + .newHandler(channel.alloc(), host, protocol.port()); // Enable hostname verification. SSLEngine sslEngine = sslHandler.engine(); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index f16658a4f90..69d5b7f1603 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,20 +14,24 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.ProbingAction.PROBING_ACTION_KEY; +import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; -import google.registry.monitoring.blackbox.Prober; import google.registry.monitoring.blackbox.Protocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; +import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; -import google.registry.monitoring.blackbox.exceptions.ServerSideException; +import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import java.net.MalformedURLException; import java.net.URL; @@ -44,26 +48,60 @@ public class WebWhoisActionHandler extends ActionHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** Dagger injected components necessary for redirect responses: */ + + /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + private final Bootstrap bootstrap; + + /** {@link Protocol} for when redirected to http endpoint. */ + private final Protocol httpWhoisProtocol; + + /** {@link Protocol} for when redirected to https endpoint. */ + private final Protocol httpsWhoisProtocol; + + /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + private final HttpRequestMessage requestMessage; + + /** Default port for http. */ + private int httpPort; + + /** default port for https. */ + private int httpsPort; + @Inject - public WebWhoisActionHandler() {} + public WebWhoisActionHandler( + @WebWhoisProtocol Bootstrap bootstrap, + @HttpWhoisProtocol Protocol httpWhoisProtocol, + @HttpsWhoisProtocol Protocol httpsWhoisProtocol, + HttpRequestMessage requestMessage, + @HttpWhoisProtocol int httpPort, + @HttpsWhoisProtocol int httpsPort) { + + this.bootstrap = bootstrap; + this.httpWhoisProtocol = httpWhoisProtocol; + this.httpsWhoisProtocol = httpsWhoisProtocol; + this.requestMessage = requestMessage; + this.httpPort = httpPort; + this.httpsPort = httpsPort; + } /** * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ServerSideException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirections until receiving one of the previous three responses + * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, + * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException { + throws ResponseException, InternalException { HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { logger.atInfo().log("Received Successful HttpResponseStatus"); - logger.atInfo().log("Response Received: " + response); + + //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { @@ -84,39 +122,49 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); //Construct new Protocol to reflect redirected host, path, and port - Protocol newProtocol = Prober.portToProtocolMap.get(newPort); - - //Obtain old ProbingAction, which we will use as a template for the new one - ProbingAction oldAction = ctx.channel().attr(PROBING_ACTION_KEY).get(); + Protocol newProtocol; + if (newPort == httpPort) { + newProtocol = httpWhoisProtocol; + } else if (newPort == httpsPort) { + newProtocol = httpsWhoisProtocol; + } else { + throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + } - //Modify HttpRequestMessage sent to remote host to reflect new path and host - HttpRequestMessage httpRequest = ((HttpRequestMessage)oldAction.outboundMessage()).setUri(newPath); - httpRequest.headers().set(HttpHeaderNames.HOST, newHost); + //Obtain HttpRequestMessage with modified headers to reflect new host and path. + HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath); //Create new probingAction that takes in the new Protocol and HttpRequestMessage with no delay - ProbingAction redirectedAction = oldAction.toBuilder() - .protocol(newProtocol) - .outboundMessage(httpRequest) - .delay(Duration.ZERO) - .host(newHost) - .path(newPath) + ProbingAction redirectedAction = ProbingAction.builder() + .setBootstrap(bootstrap) + .setProtocol(newProtocol) + .setOutboundMessage(httpRequest) + .setDelay(Duration.ZERO) + .setHost(newHost) .build(); //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROBING_ACTION_KEY).set(redirectedAction); + ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - logger.atInfo().log("Successfully Closed Connection"); + if (f.isSuccess()) + logger.atInfo().log("Successfully Closed Connection."); + else + logger.atWarning().log("Channel was unsuccessfully closed."); //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on - secondFuture.addListener(f2 -> finished.setSuccess()); - + secondFuture.addListener(f2 -> { + if (f2.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f2.cause()); + }); } ); } else { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b06938d80a1..34338c74d86 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,19 +19,30 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import javax.inject.Inject; /** - * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest} + * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. + * + *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method + * that modifies the request to reflect the new host and optional path. We also implement a + * {@code name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { + @Inject + public HttpRequestMessage() { + this(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + } + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - public HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { super(httpVersion, method, uri, content); } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); @@ -39,18 +50,29 @@ public HttpRequestMessage setUri(String path) { } /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public static HttpRequestMessage fromRequest(FullHttpRequest request) { - HttpRequestMessage finalRequest; - ByteBuf buf = request.content(); + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } - if (buf == null) - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri()); - else - finalRequest = new HttpRequestMessage(HttpVersion.HTTP_1_1, request.method(), request.uri(), buf); + /** Modifies headers to reflect new host and new path if applicable. */ + @Override + public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { + if (args.length == 1 || args.length == 2) { + headers().set("host", args[0]); + if (args.length == 2) + setUri(args[1]); + + return this; - request.headers().forEach((entry) -> finalRequest.headers().set(entry.getKey(), entry.getValue())); + } else { + throw new IllegalArgumentException(); + } + } - return finalRequest; + @Override + public String name() { + return String.format("Http(s) Request on: %s", headers().get("host")); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 283b14440ac..03e16dd42cb 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -34,17 +34,9 @@ public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteB } /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public static HttpResponseMessage fromResponse(FullHttpResponse response) { - HttpResponseMessage finalResponse; - ByteBuf buf = response.content(); + public HttpResponseMessage (FullHttpResponse response) { + this(response.protocolVersion(), response.status(), response.content()); - if (buf == null) - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status()); - else - finalResponse = new HttpResponseMessage(HttpVersion.HTTP_1_1, response.status(), buf); - - response.headers().forEach((entry) -> finalResponse.headers().set(entry.getKey(), entry.getValue())); - - return finalResponse; + response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); } } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt new file mode 100644 index 00000000000..2efb15a507d --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt @@ -0,0 +1 @@ +epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt new file mode 100644 index 00000000000..9aa28d4bd9a --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt @@ -0,0 +1 @@ +passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt new file mode 100644 index 00000000000..0808c6b3cd2 --- /dev/null +++ b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt @@ -0,0 +1 @@ +insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 new file mode 100644 index 0000000000000000000000000000000000000000..4b6f30a3732e571007a4417cb644ff347b5b85f2 GIT binary patch literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( Date: Mon, 29 Jul 2019 12:04:58 -0400 Subject: [PATCH 310/337] Minor Style Fixes --- .../monitoring/blackbox/ProbingAction.java | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 7f7aa801f6e..3f6a962b12d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -89,11 +90,47 @@ public abstract class ProbingAction implements Callable { public abstract String host(); /** The {@link SocketAddress} instance that specifies remote address of connection */ + @Nullable public abstract SocketAddress address(); /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ public abstract Optional bootstrap(); + + public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { + // Write appropriate outboundMessage to pipeline + ChannelFuture channelFuture = actionHandler.getFuture(); + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + //reset the future associated with our ActionHandler in case channel is reused + future -> actionHandler.resetFuture(), + + //inform ProbingStep of the status of our action + future -> { + if (future.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(future.cause()); + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) + logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); + else + logger.atWarning() + .log("Could not close channel. Stale connection still exists."); + } + ); + } + } + ); + } + /** * The method that performs the work of the actual action. * @@ -130,41 +167,13 @@ public ChannelFuture performAction() throws InternalException { ActionHandler finalActionHandler = actionHandler; //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - timer.newTimeout(timeout -> { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = finalActionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> finalActionHandler.resetFuture(), - - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - }, - delay().getStandardSeconds(), - TimeUnit.SECONDS); + if (delay() == Duration.ZERO) + informListeners(finished, finalActionHandler); + else + timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), + delay().getStandardSeconds(), + TimeUnit.SECONDS); + return finished; } @@ -224,7 +233,7 @@ public abstract static class Builder { abstract Channel channel(); - abstract Optional address(); + abstract SocketAddress address(); abstract Optional bootstrap(); @@ -233,7 +242,7 @@ public abstract static class Builder { abstract ProbingAction autoBuild(); public ProbingAction build() { - if (!address().isPresent()) + if (address() == null) //If no address has been supplied, we set it based on the host and port setAddress(new InetSocketAddress(host(), protocol().port())); @@ -259,7 +268,7 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address().get()); + ChannelFuture connectionFuture = bootstrap().get().connect(address()); setChannel(connectionFuture.channel()); setConnectionFuture(connectionFuture); From 280a648ee81a61667fec0544b66b315abb888502 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:05:59 -0400 Subject: [PATCH 311/337] Updated build.gradle file --- prober/build.gradle | 8 - .../blackbox/ProbingSequenceStepTest.java | 219 ------------------ 2 files changed, 227 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java diff --git a/prober/build.gradle b/prober/build.gradle index b23314728e1..bb3b59ce8d7 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -16,8 +16,6 @@ apply plugin: 'java' createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober') - - dependencies { def deps = rootProject.dependencyMap @@ -46,7 +44,6 @@ dependencies { testCompile deps['junit:junit'] testCompile deps['org.mockito:mockito-core'] testCompile project(':third_party') - //testCompile project(path: ':core', configuration: 'testRuntime') // Include auto-value in compile until nebula-lint understands // annotationProcessor @@ -55,8 +52,3 @@ dependencies { annotationProcessor deps['com.google.dagger:dagger-compiler'] testAnnotationProcessor deps['com.google.dagger:dagger-compiler'] } - -task(runMain, dependsOn: 'classes', type: JavaExec) { - main = 'google.registry.monitoring.blackbox.Prober' - classpath = sourceSets.main.runtimeClasspath -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java deleted file mode 100644 index 7a713017072..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceStepTest.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.TestUtils.DummyStep; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; -import google.registry.monitoring.blackbox.TestUtils.TestProvider; -import google.registry.monitoring.blackbox.TestUtils.TestStep; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.handlers.ActionHandler; -import google.registry.monitoring.blackbox.handlers.ConversionHandler; -import google.registry.monitoring.blackbox.handlers.NettyRule; -import google.registry.monitoring.blackbox.handlers.TestActionHandler; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultPromise; -import javax.inject.Provider; -import org.junit.Rule; -import org.junit.Test; - -/** Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific implementations*/ -public class ProbingSequenceStepTest { - - /** Basic Constants necessary for tests */ - private final String ADDRESS_NAME = "TEST_ADDRESS"; - private final String PROTOCOL_NAME = "TEST_PROTOCOL"; - private final int PROTOCOL_PORT = 0; - private final String TEST_MESSAGE = "TEST_MESSAGE"; - private final String SECONDARY_TEST_MESSAGE = "SECONDARY_TEST_MESSAGE"; - - private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1); - private final LocalAddress address = new LocalAddress(ADDRESS_NAME); - - /** Used for testing how well probing step can create connection to blackbox server */ - @Rule - public NettyRule nettyRule = new NettyRule(eventLoopGroup); - - - /** The two main handlers we need in any test pipeline used that connects to {@link NettyRule's server}**/ - private ActionHandler testHandler = new TestActionHandler(); - private ChannelHandler conversionHandler = new ConversionHandler(); - - /** Wrapper provider classes of these handlers */ - private Provider testHandlerProvider = new TestProvider<>(testHandler); - private Provider conversionHandlerProvider = new TestProvider<>(conversionHandler); - - /** Embedded Channel and Protocol both are stated, but not specified until we know which test we are running) */ - private EmbeddedChannel channel; - private Protocol testProtocol; - - - - /** Fields that correspond to instances of each of the above {@link ProbingStep} classes in the same order */ - private ProbingStep firstStep; - private ProbingStep dummyStep; - - /** Never explicitly used, but our ProbingStep depends on the ProbingSequence to function, so we create a declare a throwaway ProbingSequence */ - private ProbingSequence testSequence; - - /** We declare the token we feed into our probing step, but will specify what kind it is, depending on if we are creating a new channel or reusing one */ - private Token testToken; - - /** Sets up testToken to return arbitrary values, and no channel. Used when we create a new channel */ - private void setupNewChannelToken() { - testToken = new NewChannelToken(""); - } - - /** Sets up testToken to return arbitrary value, and the embedded channel. Used for when the ProbingStep generates an ExistingChannelAction */ - private void setupExistingChannelToken() { - testToken = new ExistingChannelToken(channel, ""); - } - - /** Sets up an embedded channel to contain the two handlers we created already */ - private void setupChannel() { - channel = new EmbeddedChannel(conversionHandler, testHandler); - } - - /** Sets up our main step (firstStep) and throwaway step (dummyStep) */ - private void setupSteps() { - firstStep = new TestStep(testProtocol, TEST_MESSAGE, address); - dummyStep = new DummyStep(testProtocol, eventLoopGroup); - } - - /** Sets up testProtocol for when we create a new channel */ - private void setupNewProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(false) - .build(); - } - - /** Sets up testProtocol for when a channel already exists */ - private void setupExistingProtocol() { - testProtocol = Protocol.builder() - .handlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) - .name(PROTOCOL_NAME) - .port(PROTOCOL_PORT) - .persistentConnection(true) - .build(); - } - - /** Builds a sequence with our probing steps and the EventLoopGroup we initialized */ - private void setupSequence() { - testSequence = new ProbingSequence.Builder() - .eventLoopGroup(eventLoopGroup) - .setClass(LocalChannel.class) - .addStep(firstStep) - .makeFirstRepeated() - .addStep(dummyStep) - .build(); - } - - - @Test - public void testGeneralBehavior() { - //setup - setupNewProtocol(); - setupSteps(); - setupNewChannelToken(); - - //there should be no next step - assertThat(firstStep.nextStep()).isNull(); - - //we expect that this exception be thrown - assertThrows(NullPointerException.class, () -> firstStep.accept(testToken)); - - } - - @Test - public void testWithSequence_NewChannel() throws Exception { - //setup - setupNewProtocol(); - setupSteps(); - setupSequence(); - setupNewChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Set up blackbox server that recieves our messages then echoes them back to us - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); - - //Call accept on the first step, which should send our message to the server, which will then be - //echoed back to us, causing us to move to the next step - firstStep.accept(testToken); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //checks that we have appropriately sent the write message to server - nettyRule.assertThatCustomWorks(TEST_MESSAGE); - - //checks that when the future is successful, we pass down the requisite token - assertThat(future.get()).isEqualTo(testToken); - - } - - @Test - public void testWithSequence_ExistingChannel() throws Exception { - //setup - setupExistingProtocol(); - setupSteps(); - setupSequence(); - setupChannel(); - setupExistingChannelToken(); - - //checks that the ProbingSteps are appropriately pointing to each other - assertThat(firstStep.nextStep()).isEqualTo(dummyStep); - assertThat(dummyStep.nextStep()).isEqualTo(firstStep); - - //Call accept on the first step, which should send our message through the EmbeddedChannel pipeline - firstStep.accept(testToken); - - //Ensures the accurate message is sent down the pipeline - assertThat(((ByteBuf)channel.readOutbound()).toString(UTF_8)).isEqualTo(TEST_MESSAGE); - - //Obtains future for when we have moved to the next step - DefaultPromise future = ((DummyStep)dummyStep).getFuture(); - - //Write response to our message down EmbeddedChannel pipeline - channel.writeInbound(Unpooled.wrappedBuffer(SECONDARY_TEST_MESSAGE.getBytes(US_ASCII))); - - //At this point, we should have received the message, so the future obtained should be marked as a success - assertThat(future.isSuccess()); - - //checks that the requisite token is passed down - assertThat(future.get()).isEqualTo(testToken); - - } -} From a2788bc8a046023dfad0409ee1bdd5d3d961da89 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:14:24 -0400 Subject: [PATCH 312/337] Modified license header dates --- core/src/main/java/google/registry/ui/package-info.java | 2 +- core/src/main/java/google/registry/xjc/package-info.java | 2 +- .../google/registry/proxy/handler/SslClientInitializer.java | 2 +- .../src/test/java/google/registry/proxy/handler/NettyRule.java | 2 +- .../google/registry/proxy/handler/SslClientInitializerTest.java | 2 +- .../google/registry/proxy/handler/SslInitializerTestUtils.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index d65a45f3ac3..97f82e35721 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index 15f19b47989..daec08eb483 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java index d5d56469b36..e8c200b08e2 100644 --- a/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java +++ b/proxy/src/main/java/google/registry/proxy/handler/SslClientInitializer.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java index 95b449dbc89..c0fbdae28b3 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java +++ b/proxy/src/test/java/google/registry/proxy/handler/NettyRule.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// Copyright 2018 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java index 440e4908417..c6232d847b4 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslClientInitializerTest.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. diff --git a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java index 1b923b7eae3..8e98ee5fc70 100644 --- a/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java +++ b/proxy/src/test/java/google/registry/proxy/handler/SslInitializerTestUtils.java @@ -1,4 +1,4 @@ -// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// 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. From a1efc6ffef9af70a088076c7cd3dbfccfb1df81a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 29 Jul 2019 15:54:13 -0400 Subject: [PATCH 313/337] Updated WebWhois tests. --- .../registry/monitoring/blackbox/TokenTest.java | 13 +++++++------ .../blackbox/handlers/ConversionHandler.java | 2 +- .../blackbox/handlers/TestActionHandler.java | 6 ++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java index ef5cba5b60d..67963805733 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java @@ -16,10 +16,11 @@ import static com.google.common.truth.Truth.assertThat; -import google.registry.monitoring.blackbox.Tokens.Token; -import google.registry.monitoring.blackbox.Tokens.WebWhoisToken; +import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; +import google.registry.monitoring.blackbox.tokens.Token; +import google.registry.monitoring.blackbox.tokens.WebWhoisToken; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import org.junit.Test; @@ -34,20 +35,20 @@ public class TokenTest { private static String PREFIX = "whois.nic."; private static String TEST_STARTER = "starter"; - private static String TEST_DOMAIN = "test"; + private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(TEST_DOMAIN); + public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + HttpRequestMessage message = new HttpRequestMessage(); message.headers().set("host", TEST_STARTER); //attempts to use Token's method for modifying the method based on its stored host try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAIN); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); } catch(InternalException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index b5363aa8139..a8506a996a9 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -37,7 +37,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - super.channelRead(ctx, new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 3357f14f6c5..0c078948be4 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox.handlers; +import google.registry.monitoring.blackbox.exceptions.InternalException; import google.registry.monitoring.blackbox.exceptions.ResponseException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -22,12 +23,13 @@ * Concrete implementation of {@link ActionHandler} that does nothing different from parent class * other than store and return the {@code inboundMessage} */ -public class TestActionHandler extends ActionHandler{ +public class TestActionHandler extends ActionHandler { private String receivedMessage; @Override - public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws ResponseException { + public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) + throws ResponseException, InternalException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } From 390c951024d9c79984a2e992b6c50c3f99bc0b5e Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:46:06 -0400 Subject: [PATCH 314/337] Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring --- prober/.gitignore | 2 +- .../registry/monitoring/blackbox/Prober.java | 9 +- .../monitoring/blackbox/ProbingAction.java | 96 ++++++++---------- .../exceptions/ConnectionException.java | 5 +- .../blackbox/exceptions/FailureException.java | 15 ++- .../exceptions/InternalException.java | 30 ------ .../exceptions/ResponseException.java | 29 ------ .../handlers/WebWhoisActionHandler.java | 51 ++++------ .../blackbox/messages/HttpRequestMessage.java | 4 +- .../messages/HttpResponseMessage.java | 6 +- .../blackbox/modules/secrets/epp_host.txt | 1 - .../modules/secrets/keystore_password.txt | 1 - .../blackbox/modules/secrets/password.txt | 1 - .../secrets/prober-client-tls-sandbox.p12 | Bin 1717 -> 0 bytes .../blackbox/modules/secrets/user_id.txt | 1 - .../monitoring/blackbox/TokenTest.java | 8 +- .../blackbox/handlers/TestActionHandler.java | 6 +- 17 files changed, 99 insertions(+), 166 deletions(-) delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 delete mode 100644 prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/user_id.txt diff --git a/prober/.gitignore b/prober/.gitignore index c86568e7672..77b1e2de2de 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index b9a89a9382b..307afd34d81 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -15,6 +15,7 @@ package google.registry.monitoring.blackbox; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; +import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -28,9 +29,11 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - ProbingSequence webWhoisSequence = proberComponent.provideWebWhoisSequence(); + Set sequences = proberComponent.provideAllSequences(); - //Tells Sequence to start running - webWhoisSequence.start(); + //Tells Sequences to start running + for (ProbingSequence sequence : sequences) { + sequence.start(); + } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 3f6a962b12d..67494dd5f78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -14,25 +14,29 @@ package google.registry.monitoring.blackbox; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.flogger.StackSize.SMALL; import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.InternalException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -65,6 +69,9 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); + /** {@link AttributeKey} in channel that gives the information of the channel's host. */ public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); @@ -80,31 +87,18 @@ public abstract class ProbingAction implements Callable { /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ public abstract Channel channel(); - /** {@link ChannelFuture} object that is set to success after successful channel connection is established. */ - public abstract ChannelFuture connectionFuture(); - /** The {@link Protocol} instance that specifies type of connection */ public abstract Protocol protocol(); /** The hostname of the remote host we have a connection or will make a connection to */ public abstract String host(); - /** The {@link SocketAddress} instance that specifies remote address of connection */ - @Nullable - public abstract SocketAddress address(); - - /** The {@link Optional} that is only used in the {@link Builder} to create a connection. */ - public abstract Optional bootstrap(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { // Write appropriate outboundMessage to pipeline ChannelFuture channelFuture = actionHandler.getFuture(); channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( - //reset the future associated with our ActionHandler in case channel is reused - future -> actionHandler.resetFuture(), - //inform ProbingStep of the status of our action future -> { if (future.isSuccess()) @@ -141,7 +135,7 @@ public void informListeners(ChannelPromise finished, ActionHandler actionHandler * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - public ChannelFuture performAction() throws InternalException { + private ChannelFuture performAction() throws UndeterminedStateException { Iterator> handlerIterator = channel().pipeline().iterator(); ActionHandler actionHandler = null; @@ -154,10 +148,10 @@ public ChannelFuture performAction() throws InternalException { } } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an InternalException + //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException if (actionHandler == null) { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new InternalException("No Action Handler found in pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); } //ChannelPromise that we use to inform ProbingStep when we are finished. @@ -180,19 +174,24 @@ public ChannelFuture performAction() throws InternalException { /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws InternalException { + public ChannelFuture call() throws UndeterminedStateException { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); - //When connection is established call super.call and set returned listener to success - connectionFuture().addListener( + channel().attr(CONNECTION_FUTURE_KEY).get().addListener( (ChannelFuture channelFuture) -> { if (channelFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); ChannelFuture future = performAction(); - future.addListener(f -> finished.setSuccess()); + future.addListener( + f -> { + if (f.isSuccess()) + finished.setSuccess(); + else + finished.setFailure(f.cause()); + }); } else { //if we receive a failure, log the failure, and close the channel @@ -210,6 +209,12 @@ public ChannelFuture call() throws InternalException { /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; + + public Builder setBootstrap(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + return this; + } public abstract Builder setDelay(Duration value); @@ -221,40 +226,30 @@ public abstract static class Builder { public abstract Builder setChannel(Channel channel); - public abstract Builder setAddress(SocketAddress address); - - public abstract Builder setBootstrap(Bootstrap value); - - public abstract Builder setBootstrap(Optional value); - - public abstract Builder setConnectionFuture(ChannelFuture future); - abstract Protocol protocol(); - abstract Channel channel(); - - abstract SocketAddress address(); - - abstract Optional bootstrap(); + abstract Optional channel(); abstract String host(); abstract ProbingAction autoBuild(); public ProbingAction build() { - if (address() == null) - //If no address has been supplied, we set it based on the host and port - setAddress(new InetSocketAddress(host(), protocol().port())); - - if (protocol().persistentConnection() && channel() != null) { - //if a channel exists and we want to use it then we don't try to create one - setConnectionFuture(channel().newSucceededFuture()); - } else { - //otherwise, we must have a bootstrap present - assert(bootstrap().isPresent()); + SocketAddress address; + try { + InetAddress hostAddress = InetAddress.getByName(host()); + address = new InetSocketAddress(hostAddress, protocol().port()); + } catch (UnknownHostException e) { + System.out.println("test"); + address = new LocalAddress(host()); + } + checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + //If a channel is supplied, nothing is needed to be done - bootstrap().get().handler( + //Otherwise, a Bootstrap must be supplied and be used for creating the channel + if (!channel().isPresent()) { + bootstrap.handler( new ChannelInitializer() { @Override protected void initChannel(Channel outboundChannel) @@ -268,14 +263,11 @@ protected void initChannel(Channel outboundChannel) logger.atInfo().log("Initialized bootstrap with channel Handlers"); //ChannelFuture that performs action when connection is established - ChannelFuture connectionFuture = bootstrap().get().connect(address()); + ChannelFuture connectionFuture = bootstrap.connect(address); setChannel(connectionFuture.channel()); - setConnectionFuture(connectionFuture); - + connectionFuture.channel().attr(CONNECTION_FUTURE_KEY).set(connectionFuture); } - //we don't want to actually store Bootstrap, so set its value to Optional.empty() - setBootstrap(Optional.empty()); //now we can actually build the ProbingAction return autoBuild(); @@ -293,7 +285,7 @@ public static Builder builder() { * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds * to the pipeline, the list of handlers in the order specified */ - static void addHandlers( + private static void addHandlers( ChannelPipeline channelPipeline, ImmutableList> handlerProviders) { for (Provider handlerProvider : handlerProviders) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index be3d725c833..adb833ec629 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,9 +15,10 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the status of the action performed is ERROR. + * Subclass of {@link UndeterminedStateException} that represents all instances when + * the action performed failed due to an issue in the connection with the server. */ -public class ConnectionException extends Exception { +public class ConnectionException extends UndeterminedStateException { public ConnectionException(String msg) { super(msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java index 9f716bb2589..36687e7ac82 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/FailureException.java @@ -12,5 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.exceptions; +/** + * Base exception class for all instances when the status of the action performed is FAILURE. + */ +public class FailureException extends Exception { + + public FailureException(String msg) { + super(msg); + } + + public FailureException(Throwable e) { + super(e); + } +} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java deleted file mode 100644 index e676333489e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/InternalException.java +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the action performed fails - * due to the fault of the Prober. - */ -public class InternalException extends Exception { - - public InternalException(String msg) { - super(msg); - } - - public InternalException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java deleted file mode 100644 index d1028018602..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ResponseException.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.exceptions; - -/** - * Base exception class for all instances when the status of the action performed is FAILURE. - */ -public class ResponseException extends Exception { - - public ResponseException(String msg) { - super(msg); - } - - public ResponseException(Throwable e) { - super(e); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 69d5b7f1603..1ec4e314813 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -22,13 +22,12 @@ import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -62,27 +61,17 @@ public class WebWhoisActionHandler extends ActionHandler { /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ private final HttpRequestMessage requestMessage; - /** Default port for http. */ - private int httpPort; - - /** default port for https. */ - private int httpsPort; - @Inject public WebWhoisActionHandler( @WebWhoisProtocol Bootstrap bootstrap, @HttpWhoisProtocol Protocol httpWhoisProtocol, @HttpsWhoisProtocol Protocol httpsWhoisProtocol, - HttpRequestMessage requestMessage, - @HttpWhoisProtocol int httpPort, - @HttpsWhoisProtocol int httpsPort) { + HttpRequestMessage requestMessage) { this.bootstrap = bootstrap; this.httpWhoisProtocol = httpWhoisProtocol; this.httpsWhoisProtocol = httpsWhoisProtocol; this.requestMessage = requestMessage; - this.httpPort = httpPort; - this.httpsPort = httpsPort; } @@ -93,7 +82,7 @@ public WebWhoisActionHandler( */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { HttpResponseMessage response = (HttpResponseMessage) msg; @@ -112,7 +101,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new ResponseException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); @@ -123,12 +112,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; - if (newPort == httpPort) { + if (url.getProtocol().equals(httpWhoisProtocol.name())) { newProtocol = httpWhoisProtocol; - } else if (newPort == httpsPort) { + } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new ResponseException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -143,34 +132,38 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) .setHost(newHost) .build(); - //Mainly for testing, to check the probing action was created appropriately - ctx.channel().attr(PROTOCOL_KEY).set(newProtocol); - //close this channel as we no longer need it ChannelFuture future = ctx.close(); future.addListener( f -> { - if (f.isSuccess()) + if (f.isSuccess()) { logger.atInfo().log("Successfully Closed Connection."); - else + } else { logger.atWarning().log("Channel was unsuccessfully closed."); + } //Once channel is closed, establish new connection to redirected host, and repeat same actions ChannelFuture secondFuture = redirectedAction.call(); //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on secondFuture.addListener(f2 -> { - if (f2.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f2.cause()); + if (f2.isSuccess()) { + super.channelRead0(ctx, msg); + } else { + if (f2 instanceof FailureException) { + throw new FailureException(f2.cause()); + } else { + throw new UndeterminedStateException(f2.cause()); + } + } + }); } ); } else { //Add in metrics Handling that informs MetricsCollector the response was a FAILURE logger.atWarning().log(String.format("Received unexpected response: %s", response.status())); - throw new ResponseException("Response received from remote site was: " + response.status()); + throw new FailureException("Response received from remote site was: " + response.status()); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 34338c74d86..b4c01d06a8f 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,12 +66,12 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); } } @Override - public String name() { + public String toString() { return String.format("Http(s) Request on: %s", headers().get("host")); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index 03e16dd42cb..f1b2d6ac6a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -25,11 +25,7 @@ */ public class HttpResponseMessage extends DefaultFullHttpResponse implements InboundMessageType { - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status) { - super(version, status); - } - - public HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { + private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, ByteBuf content) { super(version, status, content); } diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt deleted file mode 100644 index 2efb15a507d..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/epp_host.txt +++ /dev/null @@ -1 +0,0 @@ -epp.registry-sandbox.google \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt deleted file mode 100644 index 9aa28d4bd9a..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/keystore_password.txt +++ /dev/null @@ -1 +0,0 @@ -passphrase \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt deleted file mode 100644 index 0808c6b3cd2..00000000000 --- a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/password.txt +++ /dev/null @@ -1 +0,0 @@ -insecure \ No newline at end of file diff --git a/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 b/prober/src/main/resources/google/registry/monitoring/blackbox/modules/secrets/prober-client-tls-sandbox.p12 deleted file mode 100644 index 4b6f30a3732e571007a4417cb644ff347b5b85f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY+DX*Ao38i%uqSQ<=Kt(gkOGL}%O(NabzMW>cAwrdZq#6Cj0ApR7iRJ3$rSFL4g zMyRd5)U;!dphXjEDVo$$5=)VwTs`OBJNJHg&wI}EJMa7H_h0~c0|X4k0PuLYm`<8q z+RibsD7YMeUxfj1{1NuY08qcbBX~IgbviCl5mm+USFzow$q~jet-&nG zh8C59=xd3((t6*PW&}w80&Q%!=dG)mR|dcFg(p3YF!dq{Wda|l0{*F1wS2ATQuwz% zBKt~4M9vfm7NNpV%`!*j!u2isgO3&z>K7L%=$xc!~i@5uydV$lLIuLVXlWwVuM3%dOvld zPA>G}xn)1RZ~v)nxiRr6R5H)FOA1Dg>mb!(#`?}VV7t5 zDC#CbYV2ZGqBFqep0UAs7#+y>HMU6|j?a*1B{B}C247;K3KfBc^Zk`3%Il_GXSH#4 z(6gUB@%mIQ!yhbvc6M;7IMf#HrDb|%D^Mak$wSiX2^r)MtZzkzoAg%Pjl0r)pY1R! zgXfByvA7_2-lfI03+NDm9Z$z%ht%m~bo=AA8tG;I>31<>VSNE(5Rq5h6bg1swn)E#3WihJ%0Zb<4#)}E{0m>i8|@NR<^5Tu*q zm^AJ4#m}|Oa zv?(Af3Vd#H9_oyo+MsIVaN5z@5d@$uSURHa<*$}AU*SeNPN;1U zS221Np2n3`x92-w*$)u6?#9OzI;P3C)r-GVrt8nU4&Cti&f>eSR||I=Czqkm>&wje zZ#^?jul;E_xSTVxYvoaldF_~>C16`C*2K2x2P6ios(Z!C7i)BP=sF#$6%1-z;$}JU zi5J#9vQvQbg>8f>^d|jr5Sh`8rbvVe3^g!n|82F{2}3!Utc6mhkvVkb$M)-;s=w_j zgbX~5QNtKwR54<3k#CVuh@uDxCadWEJ*uJWGDRcaT-TC(v( TEST_DOMAINS = ImmutableList.of("test"); - public Token webToken = new WebWhoisToken(PREFIX, TEST_DOMAINS); + public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test public void testWebToken_MessageModificationSuccess() { @@ -49,7 +47,7 @@ public void testWebToken_MessageModificationSuccess() { try { HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(InternalException e) { + } catch(UndeterminedStateException e) { throw new RuntimeException(e); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index 0c078948be4..be42536823f 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -14,8 +14,8 @@ package google.registry.monitoring.blackbox.handlers; -import google.registry.monitoring.blackbox.exceptions.InternalException; -import google.registry.monitoring.blackbox.exceptions.ResponseException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.InboundMessageType; import io.netty.channel.ChannelHandlerContext; @@ -29,7 +29,7 @@ public class TestActionHandler extends ActionHandler { @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) - throws ResponseException, InternalException { + throws FailureException, UndeterminedStateException { receivedMessage = inboundMessage.toString(); super.channelRead0(ctx, inboundMessage); } From 49d6d614f8fea0b4d15bce105c21f6b0f7b89dd1 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 1 Aug 2019 15:48:33 -0400 Subject: [PATCH 315/337] SpotlessApply run to fix style issues --- prober/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prober/.gitignore b/prober/.gitignore index 77b1e2de2de..c86568e7672 100644 --- a/prober/.gitignore +++ b/prober/.gitignore @@ -1,2 +1,2 @@ out/ -src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ \ No newline at end of file +src/main/resources/google/registry/monitoring/blackbox/modules/secrets/ From a323bfad9e50eeee109d893ad1708e8debbf46cb Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:28:40 -0400 Subject: [PATCH 316/337] Added license header and newline where appropriate. --- prober/build.gradle | 1 + .../java/google/registry/monitoring/blackbox/ProbingAction.java | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/prober/build.gradle b/prober/build.gradle index bb3b59ce8d7..3652390d0ba 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -35,6 +35,7 @@ dependencies { compile deps['joda-time:joda-time'] compile deps['org.bouncycastle:bcpkix-jdk15on'] compile deps['org.bouncycastle:bcprov-jdk15on'] + compile project(':util') runtime deps['com.google.flogger:flogger-system-backend'] runtime deps['com.google.auto.value:auto-value'] diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 67494dd5f78..a8740e21c20 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -240,7 +240,6 @@ public ProbingAction build() { InetAddress hostAddress = InetAddress.getByName(host()); address = new InetSocketAddress(hostAddress, protocol().port()); } catch (UnknownHostException e) { - System.out.println("test"); address = new LocalAddress(host()); } From d9bca3457be215095702b9fae819b60bbad8f6b0 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:29:48 -0400 Subject: [PATCH 317/337] Javadoc style fix in tests and removed unused methods --- .../monitoring/blackbox/handlers/ConversionHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index a8506a996a9..196141bb875 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -18,9 +18,12 @@ import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; +import google.registry.monitoring.blackbox.messages.InboundMessageType; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -28,7 +31,7 @@ * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessage Type} and {@link InboundMessageType} + *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} * used for conversion is the {@link DuplexMessageTest} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { From 275329149c8c7dead8d23a001b14dbea5193af38 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 5 Aug 2019 16:16:36 -0400 Subject: [PATCH 318/337] Refactored ProbingAction to minimize number of unnecessary methods --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProbingAction.java | 160 ++++++++---------- .../handlers/WebWhoisActionHandler.java | 7 +- .../blackbox/messages/HttpRequestMessage.java | 5 +- 4 files changed, 80 insertions(+), 95 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 307afd34d81..e12d1f0f522 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -14,6 +14,7 @@ package google.registry.monitoring.blackbox; +import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; import java.util.Set; @@ -29,7 +30,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.provideAllSequences(); + Set sequences = proberComponent.sequences(); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index a8740e21c20..25c3a1c17d6 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -33,10 +33,8 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.joda.time.Duration; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -69,6 +67,8 @@ public abstract class ProbingAction implements Callable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; + /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); @@ -85,6 +85,7 @@ public abstract class ProbingAction implements Callable { public abstract OutboundMessageType outboundMessage(); /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + @Nullable public abstract Channel channel(); /** The {@link Protocol} instance that specifies type of connection */ @@ -94,108 +95,89 @@ public abstract class ProbingAction implements Callable { public abstract String host(); - public void informListeners(ChannelPromise finished, ActionHandler actionHandler) { - // Write appropriate outboundMessage to pipeline - ChannelFuture channelFuture = actionHandler.getFuture(); - channel().writeAndFlush(outboundMessage()); - channelFuture.addListeners( - //inform ProbingStep of the status of our action - future -> { - if (future.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(future.cause()); - }, - //If we don't have a persistent connection, close the connection to this channel - future -> { - if (!protocol().persistentConnection()) { - - ChannelFuture closedFuture = channel().close(); - closedFuture.addListener( - f -> { - if (f.isSuccess()) - logger.atInfo().log("Closed stale channel. Moving on to next ProbingStep"); - else - logger.atWarning() - .log("Could not close channel. Stale connection still exists."); - } - ); - } - } - ); - } - /** - * The method that performs the work of the actual action. + * Performs the work of the actual action * - *

First, we establish which of the handlers in the pipeline is the {@link ActionHandler}. - * From that, we can obtain a future that is marked as a success when we receive an expected - * response from the server. Then, we send the {@code outboundMessage} down the channel pipeline, - * and when we observe a success or failure, we inform the {@link ProbingStep} of this.

+ *

First, checks if channel is active by setting a listener to perform the bulk of the work + * when the connection future is successful.

+ * + *

Once the connection is successful, we establish which of the handlers in the pipeline is + * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when + * we receive an expected response from the server.

+ * + *

Next, we set a timer set to a specified delay. After the delay has passed, we send the + * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, + * we inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - private ChannelFuture performAction() throws UndeterminedStateException { - Iterator> handlerIterator = channel().pipeline().iterator(); - ActionHandler actionHandler = null; - - //Finds the ActionHandler from the pipeline and initializes it. - while (handlerIterator.hasNext()) { - ChannelHandler currentHandler = handlerIterator.next().getValue(); - if (currentHandler instanceof ActionHandler) { - actionHandler = (ActionHandler) currentHandler; - break; - } - } - //If there is no ActionHandler in our pipeline, we have an issue, and throw an UndeterminedStateException - if (actionHandler == null) { - logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); - throw new UndeterminedStateException("No Action Handler found in pipeline"); - } - - //ChannelPromise that we use to inform ProbingStep when we are finished. - ChannelPromise finished = channel().newPromise(); - - //Necessary for use of actionHandler in lambda expression - ActionHandler finalActionHandler = actionHandler; - - //Every specified time frame by delay(), we perform the next action in our sequence and inform ProbingStep when finished - if (delay() == Duration.ZERO) - informListeners(finished, finalActionHandler); - else - timer.newTimeout(timeout -> informListeners(finished, finalActionHandler), - delay().getStandardSeconds(), - TimeUnit.SECONDS); - - - return finished; - } /** Method that calls on {@code performAction} when it is certain channel connection is established. */ @Override - public ChannelFuture call() throws UndeterminedStateException { + public ChannelFuture call() { //ChannelPromise that we return ChannelPromise finished = channel().newPromise(); + + //Ensures channel has been set up with connection future as an attribute + checkNotNull(channel().attr(CONNECTION_FUTURE_KEY).get()); + //When connection is established call super.call and set returned listener to success channel().attr(CONNECTION_FUTURE_KEY).get().addListener( - (ChannelFuture channelFuture) -> { - if (channelFuture.isSuccess()) { + (ChannelFuture connectionFuture) -> { + if (connectionFuture.isSuccess()) { logger.atInfo().log(String .format("Successful connection to remote host: %s at port: %d", host(), protocol().port())); - ChannelFuture future = performAction(); - future.addListener( - f -> { - if (f.isSuccess()) - finished.setSuccess(); - else - finished.setFailure(f.cause()); - }); + ActionHandler actionHandler; + try { + actionHandler = channel().pipeline().get(ActionHandler.class); + } catch (ClassCastException e) { + //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); + throw new UndeterminedStateException("No Action Handler found in pipeline"); + } + + ChannelFuture channelFuture = actionHandler.getFinishedFuture(); + + timer.newTimeout(timeout -> { + // Write appropriate outboundMessage to pipeline + channel().writeAndFlush(outboundMessage()); + channelFuture.addListeners( + future -> { + if (future.isSuccess()) { + finished.setSuccess(); + } else { + finished.setFailure(future.cause()); + } + }, + //If we don't have a persistent connection, close the connection to this channel + future -> { + if (!protocol().persistentConnection()) { + + ChannelFuture closedFuture = channel().close(); + closedFuture.addListener( + f -> { + if (f.isSuccess()) { + logger.atInfo() + .log("Closed stale channel. Moving on to next ProbingStep"); + } else { + logger.atWarning() + .log( + "Could not close channel. Stale connection still exists."); + } + } + ); + } + } + ); + }, + delay().getStandardSeconds(), + TimeUnit.SECONDS); } else { //if we receive a failure, log the failure, and close the channel - logger.atSevere().withCause(channelFuture.cause()).log( + logger.atSevere().withCause(connectionFuture.cause()).log( "Cannot connect to relay channel for %s channel: %s.", protocol().name(), this.channel()); ChannelFuture unusedFuture = channel().close(); @@ -228,7 +210,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract Protocol protocol(); - abstract Optional channel(); + abstract Channel channel(); abstract String host(); @@ -243,11 +225,11 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel().isPresent() ^ bootstrap != null, "Either Bootstrap must be supplied without Channel or Channel must be supplied without Bootstrap."); + checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (!channel().isPresent()) { + if (channel() == null) { bootstrap.handler( new ChannelInitializer() { @Override diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 1ec4e314813..34eac2a0118 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -93,7 +93,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); - } else if (response.status() == HttpResponseStatus.FOUND || response.status() == HttpResponseStatus.MOVED_PERMANENTLY) { + } else if (response.headers().get("location") != null) { //Obtain url to be redirected to URL url; @@ -106,9 +106,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); - int newPort = url.getDefaultPort(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, newPort, newPath)); + logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, url.getDefaultPort(), newPath)); //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; @@ -117,7 +116,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new FailureException("Redirection Location port was invalid. Given port was: " + newPort); + throw new FailureException("Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index b4c01d06a8f..5e9300d0f34 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -66,7 +66,10 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx return this; } else { - throw new IllegalArgumentException("Wrong number of arguments present for modifying HttpRequestMessage."); + throw new IllegalArgumentException( + String.format( + "Wrong number of arguments present for modifying HttpRequestMessage." + + " Received %d arguments instead of: " + args, args.length)); } } From dd3c764fd240c3cb0d1447421ed969421834c95b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 15:45:32 -0400 Subject: [PATCH 319/337] Modified tests for WebWhois according to changes suggested by laijiang. --- .../registry/monitoring/blackbox/Prober.java | 3 +- .../monitoring/blackbox/ProbingAction.java | 1 - .../monitoring/blackbox/TokenTest.java | 59 ------------------- .../blackbox/handlers/ConversionHandler.java | 6 +- .../blackbox/handlers/TestActionHandler.java | 7 +-- .../blackbox/messages/TestMessage.java | 4 ++ 6 files changed, 11 insertions(+), 69 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index e12d1f0f522..5ca423c29cc 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.monitoring.blackbox.ProberModule.ProberComponent; -import java.util.Set; /** * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. @@ -30,7 +29,7 @@ public class Prober { public static void main(String[] args) { //Obtains WebWhois Sequence provided by proberComponent - Set sequences = proberComponent.sequences(); + ImmutableSet sequences = ImmutableSet.copyOf(proberComponent.sequences()); //Tells Sequences to start running for (ProbingSequence sequence : sequences) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 25c3a1c17d6..0265390fafe 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -138,7 +138,6 @@ public ChannelFuture call() { logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } - ChannelFuture channelFuture = actionHandler.getFinishedFuture(); timer.newTimeout(timeout -> { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java deleted file mode 100644 index 295bb809a13..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TokenTest.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) - */ -@RunWith(JUnit4.class) -public class TokenTest { - - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static ImmutableList TEST_DOMAINS = ImmutableList.of("test"); - - public Token webToken = new WebWhoisToken(TEST_DOMAINS); - - @Test - public void testWebToken_MessageModificationSuccess() { - //creates Request message with header - HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); - - //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.get(0)); - } catch(UndeterminedStateException e) { - throw new RuntimeException(e); - } - - - - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index 196141bb875..c9d337d6ad8 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; -import google.registry.monitoring.blackbox.TestUtils.DuplexMessageTest; import google.registry.monitoring.blackbox.messages.InboundMessageType; import google.registry.monitoring.blackbox.messages.OutboundMessageType; +import google.registry.monitoring.blackbox.messages.TestMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; @@ -32,7 +32,7 @@ * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link DuplexMessageTest} type.

+ * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { @@ -40,7 +40,7 @@ public class ConversionHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; - ctx.fireChannelRead(new DuplexMessageTest(buf.toString(UTF_8))); + ctx.fireChannelRead(new TestMessage(buf.toString(UTF_8))); buf.release(); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java index be42536823f..19e608c97d2 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/TestActionHandler.java @@ -25,17 +25,16 @@ */ public class TestActionHandler extends ActionHandler { - private String receivedMessage; + private InboundMessageType receivedMessage; @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws FailureException, UndeterminedStateException { - receivedMessage = inboundMessage.toString(); + receivedMessage = inboundMessage; super.channelRead0(ctx, inboundMessage); } - @Override - public String toString() { + public InboundMessageType getResponse() { return receivedMessage; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index 922c3052bda..c31a9d336bd 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,6 +24,10 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; + public TestMessage() { + this(""); + } + public TestMessage(String msg) { message = msg; } From 7caf909dc0256e2d659c5a5fb82f69fd214a1e5a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Tue, 6 Aug 2019 16:42:43 -0400 Subject: [PATCH 320/337] Removed TestProvider from TestUtils. --- .../registry/monitoring/blackbox/messages/TestMessage.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java index c31a9d336bd..922c3052bda 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/messages/TestMessage.java @@ -24,10 +24,6 @@ public class TestMessage implements OutboundMessageType, InboundMessageType { private String message; - public TestMessage() { - this(""); - } - public TestMessage(String msg) { message = msg; } From 5274a991718815da31909e56702770f72fa60573 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 11:26:33 -0400 Subject: [PATCH 321/337] Updated issues in rebasing --- core/src/main/java/google/registry/ui/package-info.java | 1 - core/src/main/java/google/registry/xjc/package-info.java | 1 - 2 files changed, 2 deletions(-) diff --git a/core/src/main/java/google/registry/ui/package-info.java b/core/src/main/java/google/registry/ui/package-info.java index 97f82e35721..ddff37c6807 100644 --- a/core/src/main/java/google/registry/ui/package-info.java +++ b/core/src/main/java/google/registry/ui/package-info.java @@ -14,4 +14,3 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.ui; - diff --git a/core/src/main/java/google/registry/xjc/package-info.java b/core/src/main/java/google/registry/xjc/package-info.java index daec08eb483..5b5456585cc 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java +++ b/core/src/main/java/google/registry/xjc/package-info.java @@ -14,4 +14,3 @@ @javax.annotation.ParametersAreNonnullByDefault package google.registry.xjc; - From 1a8aa8e30da30b958bb8184a566d10d2b3fb6b8a Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:22:06 -0400 Subject: [PATCH 322/337] Added circular linked list to utils --- .../util/CircularLinkedListIterator.java | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 util/src/main/java/google/registry/util/CircularLinkedListIterator.java diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java new file mode 100644 index 00000000000..710c2f1b74f --- /dev/null +++ b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java @@ -0,0 +1,137 @@ +package google.registry.util; + +import java.util.Iterator; + +/** + * Custom class that support iteration through a circular linked list + * + * @param - Element type stored in the iterator + * + *

Is an immutable object that, when built, creates a circular pointing + * group of Entries, that allows for looped iteration. The first and last + * element in the closed loop are also stored.

+ */ +public class CircularLinkedListIterator implements Iterator { + + /** First {@link Entry} in the circular iterator. */ + private final Entry first; + + /** Last {@link Entry} in the circular iterator. */ + private final Entry last; + + /** Current {@link Entry} in iteration. */ + private Entry current; + + /** Because this is a circular linked list iterator, there is always a next element. */ + @Override + public boolean hasNext() { + return true; + } + + /** Obtains the next element by calling on the {@link Entry}'s next element. */ + @Override + public T next() { + if (current == null) + //If this is first call of next, return first element + current = first; + else + //Otherwise return element after current element + current = current.next; + + return current.data; + } + + /** Returns stored first element. */ + public T getFirst() { + return first.data; + } + + /** Returns stored last element. */ + public T getLast() { + return last.data; + } + + /** + * Node class for {@link CircularLinkedListIterator} that stores value of element + * and points to next {@link Entry}. + * + * @param - Matching element type of iterator. + */ + private static class Entry { + /** Stores the T instance. */ + T data; + + /** Saves reference to next {@link Entry} in iterator. */ + Entry next; + + /** Only needs T instance for initialization. */ + Entry(T data) { + this.data = data; + } + } + + /** + * As {@link CircularLinkedListIterator} is an immutable class, it needs + * a builder for instantiation. + * + * @param - Matching element type of iterator + * + *

Supports adding in element at a time, adding an {@link Iterable} + * of elements, and adding an variable number of elemetns.

+ * + *

Sets first element added to {@code first}, and when built, sets last added + * element to {@code last} and points it to the {@code first} element.

+ */ + public static class Builder { + /** Matching first entry in the circular iterator to be built. */ + private Entry first; + + /** {@link Entry} corresponding to most recent element added. */ + private Entry current; + + /** Sets current {@link Entry} to element added and points previous {@link Entry} to this one. */ + public Builder addElement(T element) { + Entry nextEntry = new Entry<>(element); + if (current == null) + //If this is first element added, we set it to first + first = nextEntry; + else + //Otherwise point previous Entry to this one + current.next = nextEntry; + + current = nextEntry; + return this; + } + + /** Simply calls {@code addElement}, for each element in {@code elements}. */ + public Builder addElements(Iterable elements) { + elements.forEach(this::addElement); + return this; + } + + /** Simply calls {@code addElement}, for each element in {@code elements}. */ + public Builder addElements(T... elements) { + for (T element : elements) + addElement(element); + + return this; + } + + /** Points last {@link Entry} to first {@link Entry}, and calls private constructor. */ + public CircularLinkedListIterator build() { + current.next = first; + return new CircularLinkedListIterator<>(first, current); + } + } + + /** + * After having established pointers between {@link Entry}s, sets + * first element to the first {@link Entry} added to {@link Builder} + * and sets last element to last one added to {@link Builder}. + */ + private CircularLinkedListIterator(Entry first, Entry last) { + this.first = first; + this.last = last; + this.current = first; + } +} From 3cf9fb6914bc46b4acddb7315db5d42f985aa858 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:24:42 -0400 Subject: [PATCH 323/337] License Header added --- .../registry/util/CircularLinkedListIterator.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java index 710c2f1b74f..3b633a3a2f6 100644 --- a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java +++ b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.util; import java.util.Iterator; From 6ee11135b138aa105edc802602f3db10f95d6d13 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:18:49 -0400 Subject: [PATCH 324/337] Refactored probing sequence to be circular linked list iterator --- .../util/CircularLinkedListIterator.java | 151 ------------------ 1 file changed, 151 deletions(-) delete mode 100644 util/src/main/java/google/registry/util/CircularLinkedListIterator.java diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java deleted file mode 100644 index 3b633a3a2f6..00000000000 --- a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2019 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.util; - -import java.util.Iterator; - -/** - * Custom class that support iteration through a circular linked list - * - * @param - Element type stored in the iterator - * - *

Is an immutable object that, when built, creates a circular pointing - * group of Entries, that allows for looped iteration. The first and last - * element in the closed loop are also stored.

- */ -public class CircularLinkedListIterator implements Iterator { - - /** First {@link Entry} in the circular iterator. */ - private final Entry first; - - /** Last {@link Entry} in the circular iterator. */ - private final Entry last; - - /** Current {@link Entry} in iteration. */ - private Entry current; - - /** Because this is a circular linked list iterator, there is always a next element. */ - @Override - public boolean hasNext() { - return true; - } - - /** Obtains the next element by calling on the {@link Entry}'s next element. */ - @Override - public T next() { - if (current == null) - //If this is first call of next, return first element - current = first; - else - //Otherwise return element after current element - current = current.next; - - return current.data; - } - - /** Returns stored first element. */ - public T getFirst() { - return first.data; - } - - /** Returns stored last element. */ - public T getLast() { - return last.data; - } - - /** - * Node class for {@link CircularLinkedListIterator} that stores value of element - * and points to next {@link Entry}. - * - * @param - Matching element type of iterator. - */ - private static class Entry { - /** Stores the T instance. */ - T data; - - /** Saves reference to next {@link Entry} in iterator. */ - Entry next; - - /** Only needs T instance for initialization. */ - Entry(T data) { - this.data = data; - } - } - - /** - * As {@link CircularLinkedListIterator} is an immutable class, it needs - * a builder for instantiation. - * - * @param - Matching element type of iterator - * - *

Supports adding in element at a time, adding an {@link Iterable} - * of elements, and adding an variable number of elemetns.

- * - *

Sets first element added to {@code first}, and when built, sets last added - * element to {@code last} and points it to the {@code first} element.

- */ - public static class Builder { - /** Matching first entry in the circular iterator to be built. */ - private Entry first; - - /** {@link Entry} corresponding to most recent element added. */ - private Entry current; - - /** Sets current {@link Entry} to element added and points previous {@link Entry} to this one. */ - public Builder addElement(T element) { - Entry nextEntry = new Entry<>(element); - if (current == null) - //If this is first element added, we set it to first - first = nextEntry; - else - //Otherwise point previous Entry to this one - current.next = nextEntry; - - current = nextEntry; - return this; - } - - /** Simply calls {@code addElement}, for each element in {@code elements}. */ - public Builder addElements(Iterable elements) { - elements.forEach(this::addElement); - return this; - } - - /** Simply calls {@code addElement}, for each element in {@code elements}. */ - public Builder addElements(T... elements) { - for (T element : elements) - addElement(element); - - return this; - } - - /** Points last {@link Entry} to first {@link Entry}, and calls private constructor. */ - public CircularLinkedListIterator build() { - current.next = first; - return new CircularLinkedListIterator<>(first, current); - } - } - - /** - * After having established pointers between {@link Entry}s, sets - * first element to the first {@link Entry} added to {@link Builder} - * and sets last element to last one added to {@link Builder}. - */ - private CircularLinkedListIterator(Entry first, Entry last) { - this.first = first; - this.last = last; - this.current = first; - } -} From 20b1d17e58475733f957939484a30430e4ed3633 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 09:57:34 -0400 Subject: [PATCH 325/337] ProbingStepTest modified to have fewer unnecessary helper methods --- .../google/registry/monitoring/blackbox/ProbingStepTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 81c7e31ce95..cb9f143e94e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -99,6 +99,7 @@ public void testProbingActionGenerate_embeddedChannel() throws UndeterminedState .setProtocol(testProtocol) .build(); + ProbingAction testAction = testStep.generateAction(testToken); assertThat(testAction.channel()).isEqualTo(channel); From 116af1bfaf78384573ca9cef9298a49cd04d07d2 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:22:06 -0400 Subject: [PATCH 326/337] Added circular linked list to utils --- .../util/CircularLinkedListIterator.java | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 util/src/main/java/google/registry/util/CircularLinkedListIterator.java diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java new file mode 100644 index 00000000000..710c2f1b74f --- /dev/null +++ b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java @@ -0,0 +1,137 @@ +package google.registry.util; + +import java.util.Iterator; + +/** + * Custom class that support iteration through a circular linked list + * + * @param - Element type stored in the iterator + * + *

Is an immutable object that, when built, creates a circular pointing + * group of Entries, that allows for looped iteration. The first and last + * element in the closed loop are also stored.

+ */ +public class CircularLinkedListIterator implements Iterator { + + /** First {@link Entry} in the circular iterator. */ + private final Entry first; + + /** Last {@link Entry} in the circular iterator. */ + private final Entry last; + + /** Current {@link Entry} in iteration. */ + private Entry current; + + /** Because this is a circular linked list iterator, there is always a next element. */ + @Override + public boolean hasNext() { + return true; + } + + /** Obtains the next element by calling on the {@link Entry}'s next element. */ + @Override + public T next() { + if (current == null) + //If this is first call of next, return first element + current = first; + else + //Otherwise return element after current element + current = current.next; + + return current.data; + } + + /** Returns stored first element. */ + public T getFirst() { + return first.data; + } + + /** Returns stored last element. */ + public T getLast() { + return last.data; + } + + /** + * Node class for {@link CircularLinkedListIterator} that stores value of element + * and points to next {@link Entry}. + * + * @param - Matching element type of iterator. + */ + private static class Entry { + /** Stores the T instance. */ + T data; + + /** Saves reference to next {@link Entry} in iterator. */ + Entry next; + + /** Only needs T instance for initialization. */ + Entry(T data) { + this.data = data; + } + } + + /** + * As {@link CircularLinkedListIterator} is an immutable class, it needs + * a builder for instantiation. + * + * @param - Matching element type of iterator + * + *

Supports adding in element at a time, adding an {@link Iterable} + * of elements, and adding an variable number of elemetns.

+ * + *

Sets first element added to {@code first}, and when built, sets last added + * element to {@code last} and points it to the {@code first} element.

+ */ + public static class Builder { + /** Matching first entry in the circular iterator to be built. */ + private Entry first; + + /** {@link Entry} corresponding to most recent element added. */ + private Entry current; + + /** Sets current {@link Entry} to element added and points previous {@link Entry} to this one. */ + public Builder addElement(T element) { + Entry nextEntry = new Entry<>(element); + if (current == null) + //If this is first element added, we set it to first + first = nextEntry; + else + //Otherwise point previous Entry to this one + current.next = nextEntry; + + current = nextEntry; + return this; + } + + /** Simply calls {@code addElement}, for each element in {@code elements}. */ + public Builder addElements(Iterable elements) { + elements.forEach(this::addElement); + return this; + } + + /** Simply calls {@code addElement}, for each element in {@code elements}. */ + public Builder addElements(T... elements) { + for (T element : elements) + addElement(element); + + return this; + } + + /** Points last {@link Entry} to first {@link Entry}, and calls private constructor. */ + public CircularLinkedListIterator build() { + current.next = first; + return new CircularLinkedListIterator<>(first, current); + } + } + + /** + * After having established pointers between {@link Entry}s, sets + * first element to the first {@link Entry} added to {@link Builder} + * and sets last element to last one added to {@link Builder}. + */ + private CircularLinkedListIterator(Entry first, Entry last) { + this.first = first; + this.last = last; + this.current = first; + } +} From ecfd5ea97f7087b66a7d5a550abb89e177969eaa Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 11:24:42 -0400 Subject: [PATCH 327/337] License Header added --- .../registry/util/CircularLinkedListIterator.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java index 710c2f1b74f..3b633a3a2f6 100644 --- a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java +++ b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java @@ -1,3 +1,17 @@ +// Copyright 2019 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.util; import java.util.Iterator; From 2e0fce269ef64b97bb1ca34b88d00ac5fd821134 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 2 Aug 2019 14:18:49 -0400 Subject: [PATCH 328/337] Refactored probing sequence to be circular linked list iterator --- .../util/CircularLinkedListIterator.java | 151 ------------------ 1 file changed, 151 deletions(-) delete mode 100644 util/src/main/java/google/registry/util/CircularLinkedListIterator.java diff --git a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java b/util/src/main/java/google/registry/util/CircularLinkedListIterator.java deleted file mode 100644 index 3b633a3a2f6..00000000000 --- a/util/src/main/java/google/registry/util/CircularLinkedListIterator.java +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2019 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.util; - -import java.util.Iterator; - -/** - * Custom class that support iteration through a circular linked list - * - * @param - Element type stored in the iterator - * - *

Is an immutable object that, when built, creates a circular pointing - * group of Entries, that allows for looped iteration. The first and last - * element in the closed loop are also stored.

- */ -public class CircularLinkedListIterator implements Iterator { - - /** First {@link Entry} in the circular iterator. */ - private final Entry first; - - /** Last {@link Entry} in the circular iterator. */ - private final Entry last; - - /** Current {@link Entry} in iteration. */ - private Entry current; - - /** Because this is a circular linked list iterator, there is always a next element. */ - @Override - public boolean hasNext() { - return true; - } - - /** Obtains the next element by calling on the {@link Entry}'s next element. */ - @Override - public T next() { - if (current == null) - //If this is first call of next, return first element - current = first; - else - //Otherwise return element after current element - current = current.next; - - return current.data; - } - - /** Returns stored first element. */ - public T getFirst() { - return first.data; - } - - /** Returns stored last element. */ - public T getLast() { - return last.data; - } - - /** - * Node class for {@link CircularLinkedListIterator} that stores value of element - * and points to next {@link Entry}. - * - * @param - Matching element type of iterator. - */ - private static class Entry { - /** Stores the T instance. */ - T data; - - /** Saves reference to next {@link Entry} in iterator. */ - Entry next; - - /** Only needs T instance for initialization. */ - Entry(T data) { - this.data = data; - } - } - - /** - * As {@link CircularLinkedListIterator} is an immutable class, it needs - * a builder for instantiation. - * - * @param - Matching element type of iterator - * - *

Supports adding in element at a time, adding an {@link Iterable} - * of elements, and adding an variable number of elemetns.

- * - *

Sets first element added to {@code first}, and when built, sets last added - * element to {@code last} and points it to the {@code first} element.

- */ - public static class Builder { - /** Matching first entry in the circular iterator to be built. */ - private Entry first; - - /** {@link Entry} corresponding to most recent element added. */ - private Entry current; - - /** Sets current {@link Entry} to element added and points previous {@link Entry} to this one. */ - public Builder addElement(T element) { - Entry nextEntry = new Entry<>(element); - if (current == null) - //If this is first element added, we set it to first - first = nextEntry; - else - //Otherwise point previous Entry to this one - current.next = nextEntry; - - current = nextEntry; - return this; - } - - /** Simply calls {@code addElement}, for each element in {@code elements}. */ - public Builder addElements(Iterable elements) { - elements.forEach(this::addElement); - return this; - } - - /** Simply calls {@code addElement}, for each element in {@code elements}. */ - public Builder addElements(T... elements) { - for (T element : elements) - addElement(element); - - return this; - } - - /** Points last {@link Entry} to first {@link Entry}, and calls private constructor. */ - public CircularLinkedListIterator build() { - current.next = first; - return new CircularLinkedListIterator<>(first, current); - } - } - - /** - * After having established pointers between {@link Entry}s, sets - * first element to the first {@link Entry} added to {@link Builder} - * and sets last element to last one added to {@link Builder}. - */ - private CircularLinkedListIterator(Entry first, Entry last) { - this.first = first; - this.last = last; - this.current = first; - } -} From cd99c801b7fae8a7c00368a17f26b63dbfb37177 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 16:30:39 -0400 Subject: [PATCH 329/337] Fixed max column length to be 100 --- .../registry/monitoring/blackbox/Prober.java | 10 +- .../monitoring/blackbox/ProbingAction.java | 182 ++++++++++-------- .../monitoring/blackbox/Protocol.java | 11 -- .../handlers/WebWhoisActionHandler.java | 55 ++++-- .../blackbox/messages/HttpRequestMessage.java | 32 +-- .../messages/HttpResponseMessage.java | 6 +- .../monitoring/blackbox/ProbingStepTest.java | 1 - .../blackbox/handlers/ConversionHandler.java | 16 +- 8 files changed, 178 insertions(+), 135 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java index 5ca423c29cc..433d7361d5b 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Prober.java @@ -18,12 +18,16 @@ import google.registry.monitoring.blackbox.ProberModule.ProberComponent; /** - * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by Dagger. + * Main class of the Prober, which obtains and starts the {@link ProbingSequence}s provided by + * Dagger. */ public class Prober { - /** Main Dagger Component */ - private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder().build(); + /** + * Main Dagger Component + */ + private static ProberComponent proberComponent = DaggerProberModule_ProberComponent.builder() + .build(); public static void main(String[] args) { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 0265390fafe..36413b73452 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -26,75 +26,100 @@ import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.messages.OutboundMessageType; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; import io.netty.channel.local.LocalAddress; import io.netty.util.AttributeKey; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; +import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -import org.joda.time.Duration; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; -import java.util.concurrent.Callable; import javax.inject.Provider; +import org.joda.time.Duration; /** * AutoValue class that represents action generated by {@link ProbingStep} * *

Inherits from {@link Callable}, as it has can be called - * to perform its specified task, and return the {@link ChannelFuture} that will be informed when the - * task has been completed

+ * to perform its specified task, and return the {@link ChannelFuture} that will be informed when + * the task has been completed

* - *

Is an immutable class, as it is comprised of the tools necessary for making a specific type of connection. - * It goes hand in hand with {@link Protocol}, which specifies the kind of overall connection to be made. {@link Protocol} - * gives the outline and {@link ProbingAction} gives the details of that connection.

+ *

Is an immutable class, as it is comprised of the tools necessary for making a specific type + * of connection. It goes hand in hand with {@link Protocol}, which specifies the kind of overall + * connection to be made. {@link Protocol} gives the outline and {@link ProbingAction} gives the + * details of that connection.

* - *

In its build, if there is no channel supplied, it will create a channel from the attributes already supplied. - * Then, it only sends the {@link OutboundMessageType} down the pipeline when informed that the connection is successful. - * If the channel is supplied, the connection future is automatically set to successful.

+ *

In its build, if there is no channel supplied, it will create a channel from the attributes + * already supplied. Then, it only sends the {@link OutboundMessageType} down the pipeline when + * informed that the connection is successful. If the channel is supplied, the connection future is + * automatically set to successful.

*/ @AutoValue public abstract class ProbingAction implements Callable { + /** + * {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when + * channel is active. + */ + public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey + .valueOf("CONNECTION_FUTURE_KEY"); + /** + * {@link AttributeKey} in channel that gives the information of the channel's host. + */ + public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey + .valueOf("REMOTE_ADDRESS_KEY"); private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + /** + * {@link Timer} that rate limits probing + */ + private static final Timer timer = new HashedWheelTimer(); - private final static String HANDLER_IDENTIFIER_STRING = "ACTION_HANDLER"; - - /** {@link AttributeKey} in channel that gives {@link ChannelFuture} that is set to success when channel is active. */ - public static final AttributeKey CONNECTION_FUTURE_KEY = AttributeKey.valueOf("CONNECTION_FUTURE_KEY"); - - /** {@link AttributeKey} in channel that gives the information of the channel's host. */ - public static final AttributeKey REMOTE_ADDRESS_KEY = AttributeKey.valueOf("REMOTE_ADDRESS_KEY"); + public static Builder builder() { + return new AutoValue_ProbingAction.Builder(); + } - /** {@link Timer} that rate limits probing */ - private static final Timer timer = new HashedWheelTimer(); + /** + * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified + * + * @param channelPipeline is pipeline associated with channel that we want to add handlers to + * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds + * to the pipeline, the list of handlers in the order specified + */ + private static void addHandlers( + ChannelPipeline channelPipeline, + ImmutableList> handlerProviders) { + for (Provider handlerProvider : handlerProviders) { + channelPipeline.addLast(handlerProvider.get()); + } + } - /** Actual {@link Duration} of this delay */ + /** + * Actual {@link Duration} of this delay + */ public abstract Duration delay(); - /** {@link OutboundMessageType} instance that we write and flush down pipeline to server */ + /** + * {@link OutboundMessageType} instance that we write and flush down pipeline to server + */ public abstract OutboundMessageType outboundMessage(); - /** {@link Channel} object that either created by or passed into this {@link ProbingAction} instance */ + /** + * {@link Channel} object that either created by or passed into this {@link ProbingAction} + * instance + */ @Nullable public abstract Channel channel(); - /** The {@link Protocol} instance that specifies type of connection */ - public abstract Protocol protocol(); - - /** The hostname of the remote host we have a connection or will make a connection to */ - public abstract String host(); - - /** * Performs the work of the actual action * @@ -112,8 +137,20 @@ public abstract class ProbingAction implements Callable { * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ + /** + * The {@link Protocol} instance that specifies type of connection + */ + public abstract Protocol protocol(); + + /** + * The hostname of the remote host we have a connection or will make a connection to + */ + public abstract String host(); - /** Method that calls on {@code performAction} when it is certain channel connection is established. */ + /** + * Method that calls on {@code performAction} when it is certain channel connection is + * established. + */ @Override public ChannelFuture call() { //ChannelPromise that we return @@ -134,7 +171,8 @@ public ChannelFuture call() { try { actionHandler = channel().pipeline().get(ActionHandler.class); } catch (ClassCastException e) { - //If we don't actually have an ActionHandler instance, we have an issue, and throw an UndeterminedStateException + //If we don't actually have an ActionHandler instance, we have an issue, and throw + // an UndeterminedStateException logger.atSevere().withStackTrace(SMALL).log("ActionHandler not in Channel Pipeline"); throw new UndeterminedStateException("No Action Handler found in pipeline"); } @@ -142,16 +180,17 @@ public ChannelFuture call() { timer.newTimeout(timeout -> { // Write appropriate outboundMessage to pipeline - channel().writeAndFlush(outboundMessage()); + ChannelFuture unusedflushFuture = channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( future -> { if (future.isSuccess()) { - finished.setSuccess(); + ChannelFuture unusedFuture = finished.setSuccess(); } else { - finished.setFailure(future.cause()); + ChannelFuture unusedFuture = finished.setFailure(future.cause()); } }, - //If we don't have a persistent connection, close the connection to this channel + //If we don't have a persistent connection, close the connection to this + // channel future -> { if (!protocol().persistentConnection()) { @@ -164,7 +203,8 @@ public ChannelFuture call() { } else { logger.atWarning() .log( - "Could not close channel. Stale connection still exists."); + "Could not close channel. Stale connection still exists" + + "."); } } ); @@ -186,10 +226,26 @@ public ChannelFuture call() { return finished; } + @Override + public final String toString() { + return String.format( + "ProbingAction with delay: %d\n" + + "outboundMessage: %s\n" + + "protocol: %s\n" + + "host: %s\n", + delay().getStandardSeconds(), + outboundMessage(), + protocol(), + host() + ); + } - /** {@link AutoValue.Builder} that does work of creating connection when not already present. */ + /** + * {@link AutoValue.Builder} that does work of creating connection when not already present. + */ @AutoValue.Builder public abstract static class Builder { + private Bootstrap bootstrap; public Builder setBootstrap(Bootstrap bootstrap) { @@ -224,7 +280,8 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel() == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); + checkArgument(channel() == null ^ bootstrap == null, + "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel @@ -253,39 +310,4 @@ protected void initChannel(Channel outboundChannel) return autoBuild(); } } - - public static Builder builder() { - return new AutoValue_ProbingAction.Builder(); - } - - /** - * Adds provided {@link ChannelHandler}s to the {@link ChannelPipeline} specified - * - * @param channelPipeline is pipeline associated with channel that we want to add handlers to - * @param handlerProviders are a list of provider objects that give us the requisite handlers Adds - * to the pipeline, the list of handlers in the order specified - */ - private static void addHandlers( - ChannelPipeline channelPipeline, - ImmutableList> handlerProviders) { - for (Provider handlerProvider : handlerProviders) { - channelPipeline.addLast(handlerProvider.get()); - } - } - - - - @Override - public String toString() { - return String.format( - "ProbingAction with delay: %d\n" + - "outboundMessage: %s\n" + - "protocol: %s\n" + - "host: %s\n", - delay().getStandardSeconds(), - outboundMessage(), - protocol(), - host() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index d458e5cc4da..ae7b3ec0f79 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -75,15 +75,4 @@ public abstract Builder setHandlerProviders( public abstract Protocol build(); } - - @Override - public String toString() { - return String.format( - "Protocol with name: %s, port: %d, providers: %s, and persistent connection: %s", - name(), - port(), - handlerProviders(), - persistentConnection() - ); - } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index 34eac2a0118..c0f7ce8ae78 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -14,17 +14,15 @@ package google.registry.monitoring.blackbox.handlers; -import static google.registry.monitoring.blackbox.Protocol.PROTOCOL_KEY; - import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.HttpsWhoisProtocol; import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.ConnectionException; +import google.registry.monitoring.blackbox.exceptions.FailureException; +import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import google.registry.monitoring.blackbox.messages.InboundMessageType; @@ -38,10 +36,11 @@ import org.joda.time.Duration; /** - *Subclass of {@link ActionHandler} that deals with the WebWhois Sequence + * Subclass of {@link ActionHandler} that deals with the WebWhois Sequence * - *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response implies a redirection - * it follows the redirection until either an Error Response is received, or {@link HttpResponseStatus.OK} is received

+ *

Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response + * implies a redirection it follows the redirection until either an Error Response is received, or + * {@link HttpResponseStatus.OK} is received

*/ public class WebWhoisActionHandler extends ActionHandler { @@ -49,16 +48,24 @@ public class WebWhoisActionHandler extends ActionHandler { /** Dagger injected components necessary for redirect responses: */ - /** {@link Bootstrap} necessary for remaking connection on redirect response. */ + /** + * {@link Bootstrap} necessary for remaking connection on redirect response. + */ private final Bootstrap bootstrap; - /** {@link Protocol} for when redirected to http endpoint. */ + /** + * {@link Protocol} for when redirected to http endpoint. + */ private final Protocol httpWhoisProtocol; - /** {@link Protocol} for when redirected to https endpoint. */ + /** + * {@link Protocol} for when redirected to https endpoint. + */ private final Protocol httpsWhoisProtocol; - /** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */ + /** + * {@link HttpRequestMessage} that represents default GET message to be sent on redirect. + */ private final HttpRequestMessage requestMessage; @Inject @@ -76,9 +83,10 @@ public WebWhoisActionHandler( /** - * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, notes an error - * in the received {@link URL} and throws a {@link ConnectionException}, received a response indicating a Failure, - * or receives a redirection response, where it follows the redirects until receiving one of the previous three responses. + * After receiving {@link HttpResponseMessage}, either notes success and marks future as finished, + * notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a + * response indicating a Failure, or receives a redirection response, where it follows the + * redirects until receiving one of the previous three responses. */ @Override public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) @@ -86,7 +94,7 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) HttpResponseMessage response = (HttpResponseMessage) msg; - if (response.status() == HttpResponseStatus.OK) { + if (response.status().equals(HttpResponseStatus.OK)) { logger.atInfo().log("Received Successful HttpResponseStatus"); logger.atInfo().log("Response Received: " + response); @@ -101,13 +109,17 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) url = new URL(response.headers().get("Location")); } catch (MalformedURLException e) { //in case of error, log it, and let ActionHandler's exceptionThrown method deal with it - throw new FailureException("Redirected Location was invalid. Given Location was: " + response.headers().get("Location")); + throw new FailureException( + "Redirected Location was invalid. Given Location was: " + response.headers() + .get("Location")); } //From url, extract new host, port, and path String newHost = url.getHost(); String newPath = url.getPath(); - logger.atInfo().log(String.format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, url.getDefaultPort(), newPath)); + logger.atInfo().log(String + .format("Redirected to %s with host: %s, port: %d, and path: %s", url, newHost, + url.getDefaultPort(), newPath)); //Construct new Protocol to reflect redirected host, path, and port Protocol newProtocol; @@ -116,7 +128,8 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) } else if (url.getProtocol().equals(httpsWhoisProtocol.name())) { newProtocol = httpsWhoisProtocol; } else { - throw new FailureException("Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); + throw new FailureException( + "Redirection Location port was invalid. Given protocol name was: " + url.getProtocol()); } //Obtain HttpRequestMessage with modified headers to reflect new host and path. @@ -141,10 +154,12 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) logger.atWarning().log("Channel was unsuccessfully closed."); } - //Once channel is closed, establish new connection to redirected host, and repeat same actions + //Once channel is closed, establish new connection to redirected host, and repeat + // same actions ChannelFuture secondFuture = redirectedAction.call(); - //Once we have a successful call, set original ChannelPromise as success to tell ProbingStep we can move on + //Once we have a successful call, set original ChannelPromise as success to tell + // ProbingStep we can move on secondFuture.addListener(f2 -> { if (f2.isSuccess()) { super.channelRead0(ctx, msg); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 5e9300d0f34..57b4bc2f575 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -19,14 +19,15 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import java.util.Arrays; import javax.inject.Inject; /** * {@link OutboundMessageType} subtype that acts identically to {@link DefaultFullHttpRequest}. * *

As it is an {@link OutboundMessageType} subtype, there is a {@code modifyMessage} method - * that modifies the request to reflect the new host and optional path. We also implement a - * {@code name} method, which returns a standard name and the current hostname.

+ * that modifies the request to reflect the new host and optional path. We also implement a {@code + * name} method, which returns a standard name and the current hostname.

*/ public class HttpRequestMessage extends DefaultFullHttpRequest implements OutboundMessageType { @@ -38,30 +39,37 @@ public HttpRequestMessage() { private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri) { super(httpVersion, method, uri); } - private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { + + private HttpRequestMessage(HttpVersion httpVersion, HttpMethod method, String uri, + ByteBuf content) { super(httpVersion, method, uri, content); } + /** + * Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} + */ + public HttpRequestMessage(FullHttpRequest request) { + this(request.protocolVersion(), request.method(), request.uri(), request.content()); + request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); + } + @Override public HttpRequestMessage setUri(String path) { super.setUri(path); return this; } - /** Used for conversion from {@link FullHttpRequest} to {@link HttpRequestMessage} */ - public HttpRequestMessage(FullHttpRequest request) { - this(request.protocolVersion(), request.method(), request.uri(), request.content()); - request.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); - } - - /** Modifies headers to reflect new host and new path if applicable. */ + /** + * Modifies headers to reflect new host and new path if applicable. + */ @Override public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentException { if (args.length == 1 || args.length == 2) { headers().set("host", args[0]); - if (args.length == 2) + if (args.length == 2) { setUri(args[1]); + } return this; @@ -69,7 +77,7 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx throw new IllegalArgumentException( String.format( "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + args, args.length)); + + " Received %d arguments instead of: " + Arrays.toString(args), args.length)); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java index f1b2d6ac6a7..7d2ff722076 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpResponseMessage.java @@ -29,8 +29,10 @@ private HttpResponseMessage(HttpVersion version, HttpResponseStatus status, Byte super(version, status, content); } - /** Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} */ - public HttpResponseMessage (FullHttpResponse response) { + /** + * Used for pipeline conversion from {@link FullHttpResponse} to {@link HttpResponseMessage} + */ + public HttpResponseMessage(FullHttpResponse response) { this(response.protocolVersion(), response.status(), response.content()); response.headers().forEach((entry) -> headers().set(entry.getKey(), entry.getValue())); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index cb9f143e94e..81c7e31ce95 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -99,7 +99,6 @@ public void testProbingActionGenerate_embeddedChannel() throws UndeterminedState .setProtocol(testProtocol) .build(); - ProbingAction testAction = testStep.generateAction(testToken); assertThat(testAction.channel()).isEqualTo(channel); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java index c9d337d6ad8..987abbfd7dc 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/ConversionHandler.java @@ -28,15 +28,17 @@ import io.netty.channel.ChannelPromise; /** - * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to - * to {@link ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} + * {@link ChannelHandler} used in tests to convert {@link OutboundMessageType} to to {@link + * ByteBuf}s and convert {@link ByteBuf}s to {@link InboundMessageType} * - *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} - * used for conversion is the {@link TestMessage} type.

+ *

Specific type of {@link OutboundMessageType} and {@link InboundMessageType} + * used for conversion is the {@link TestMessage} type.

*/ public class ConversionHandler extends ChannelDuplexHandler { - /** Handles inbound conversion */ + /** + * Handles inbound conversion + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; @@ -44,7 +46,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception buf.release(); } - /** Handles outbound conversion */ + /** + * Handles outbound conversion + */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { From c7af35136dd51636aa9801442c950328e648d8ef Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Wed, 7 Aug 2019 17:35:21 -0400 Subject: [PATCH 330/337] Minor changes to pass style tests --- .../blackbox/TestServers/TestServer.java | 61 --------- .../blackbox/TestServers/WebWhoisServer.java | 123 ------------------ .../blackbox/handlers/NettyRule.java | 2 +- .../handlers/WebWhoisActionHandlerTest.java | 2 +- .../blackbox/testservers/WebWhoisServer.java | 3 +- 5 files changed, 3 insertions(+), 188 deletions(-) delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java deleted file mode 100644 index 008c69d8fbf..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; - -import com.google.common.collect.ImmutableList; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; -import io.netty.channel.nio.NioEventLoopGroup; - -/** - * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to - * perform - */ -public abstract class TestServer { - - TestServer(LocalAddress localAddress, ImmutableList handlers) { - this(new NioEventLoopGroup(1), localAddress, handlers); - } - - TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, - ImmutableList handlers) { - //Creates ChannelInitializer with handlers specified - ChannelInitializer serverInitializer = new ChannelInitializer() { - @Override - protected void initChannel(LocalChannel ch) { - for (ChannelHandler handler : handlers) { - ch.pipeline().addLast(handler); - } - } - }; - //Sets up serverBootstrap with specified initializer, eventLoopGroup, and using - // LocalServerChannel class - ServerBootstrap serverBootstrap = - new ServerBootstrap() - .group(eventLoopGroup) - .channel(LocalServerChannel.class) - .childHandler(serverInitializer); - - ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); - - } - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java deleted file mode 100644 index 6b8d6ff24b6..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestServers/WebWhoisServer.java +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.TestServers; - -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandler.Sharable; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.local.LocalAddress; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpServerCodec; - -/** - * {@link TestServer} subtype that performs WebWhois Services Expected - * - *

It will either redirect the client to the correct location if given the - * requisite redirect input, give the client a successful response if they give the expected final - * destination, or give the client an error message if given an unexpected host location

- */ -public class WebWhoisServer extends TestServer { - - public WebWhoisServer(LocalAddress localAddress, - ImmutableList handlers) { - super(localAddress, handlers); - } - - public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, - ImmutableList handlers) { - super(eventLoopGroup, localAddress, handlers); - } - - /** - * Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the - * HttpRequestMessage object through pipeline - */ - public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, - LocalAddress localAddress, String redirectInput, String destinationInput) { - return new WebWhoisServer( - eventLoopGroup, - localAddress, - ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) - ); - } - - /** - * Creates server that sends exactly what we expect a remote server to send as a response, by - * sending the {@link ByteBuf} of the response through pipeline - */ - public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, - String redirectInput, String destinationInput) { - return new WebWhoisServer( - eventLoopGroup, - localAddress, - ImmutableList.of( - new HttpServerCodec(), - new HttpObjectAggregator(1048576), - new RedirectHandler(redirectInput, destinationInput)) - ); - } - - /** - * Handler that will wither redirect client, give successful response, or give error messge - */ - @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { - - private String redirectInput; - private String destinationInput; - - /** - * @param redirectInput - Server will send back redirect to {@code destinationInput} when - * receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response - * when receiving a request with this host location - */ - public RedirectHandler(String redirectInput, String destinationInput) { - this.redirectInput = redirectInput; - this.destinationInput = destinationInput; - } - - /** - * Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on - * what header location is - */ - @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { - HttpResponse response; - if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true)); - } else if (request.headers().get("host").equals(destinationInput)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); - } - ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response); - - } - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index f13e129a512..ad2db4b71d5 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -28,7 +28,7 @@ import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 223f494f737..92d58b429de 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -24,7 +24,7 @@ import com.google.common.collect.ImmutableList; import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.TestServers.WebWhoisServer; +import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java index d15a8a8e3a4..238c6a7c0ae 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java @@ -110,8 +110,7 @@ public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { HttpResponse response; if (request.headers().get("host").equals(redirectInput)) { response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true, - false)); + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true)); } else if (request.headers().get("host").equals(destinationInput)) { response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); } else { From c9f1a9bc0b70f37dd8153cfa80eb83905c82b890 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 8 Aug 2019 14:19:34 -0400 Subject: [PATCH 331/337] Successful rebase onto finished web-whois branch --- .../monitoring/blackbox/ActionHandler.java | 5 - .../monitoring/blackbox/ProbingAction.java | 5 - .../monitoring/blackbox/ProbingSequence.java | 5 - .../monitoring/blackbox/ProbingStep.java | 5 - .../monitoring/blackbox/Protocol.java | 5 - .../monitoring/blackbox/TestToken.java | 5 - .../registry/monitoring/blackbox/Token.java | 5 - .../registry/monitoring/blackbox/Main.java | 8 -- .../monitoring/blackbox/ProbingFlows.java | 15 --- .../monitoring/blackbox/Protocol.java | 6 +- .../monitoring/blackbox/TestToken.java | 28 ---- .../registry/monitoring/blackbox/Token.java | 20 --- .../monitoring/blackbox/WebWhoisModule.java | 1 - .../blackbox/messages/HttpRequestMessage.java | 3 +- .../blackbox/messages/InboundMessageType.java | 3 +- .../messages/OutboundMessageType.java | 3 +- .../blackbox/ProbingActionTest.java | 14 +- .../monitoring/blackbox/TestProtocol.java | 70 ---------- .../blackbox/handlers/NettyRule.java | 4 +- .../handlers/WebWhoisActionHandlerTest.java | 16 +-- .../blackbox/testservers/TestServer.java | 91 +++++++------ .../blackbox/testservers/WebWhoisServer.java | 123 ------------------ .../blackbox/tokens/WebWhoisTokenTest.java | 44 +++++-- settings.gradle | 19 ++- 24 files changed, 125 insertions(+), 378 deletions(-) delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java delete mode 100644 monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Main.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java delete mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/Token.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java delete mode 100644 prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java deleted file mode 100644 index a4d36657721..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ActionHandler.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ActionHandler { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java deleted file mode 100644 index 6b26913d425..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingAction { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java deleted file mode 100644 index 9f3617135a4..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingSequence { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java deleted file mode 100644 index b8b237a1e91..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingStep { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java deleted file mode 100644 index 75d13b3039a..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Protocol { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java deleted file mode 100644 index 98f21f8d63a..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/TestToken.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class TestToken { - -} diff --git a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java b/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java deleted file mode 100644 index 16f05be0430..00000000000 --- a/monitoring/blackbox/src/main/java/google/registry/monitoring/blackbox/Token.java +++ /dev/null @@ -1,5 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Token { - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java b/prober/src/main/java/google/registry/monitoring/blackbox/Main.java deleted file mode 100644 index 61699ce033c..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Main.java +++ /dev/null @@ -1,8 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class Main { - public static void main(String[] args) { - System.out.println("Hello, world!"); - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java deleted file mode 100644 index 73dfd778d69..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingFlows.java +++ /dev/null @@ -1,15 +0,0 @@ -package google.registry.monitoring.blackbox; - -public class ProbingFlows { - - public static void main(String[] args) { - ProbingSequence sequence = new ProbingSequence - .Builder() - .addStep(new ProbingStep()) - .build(); - - sequence.start(); - - - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java index ae7b3ec0f79..ea2a6130380 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/Protocol.java @@ -60,9 +60,11 @@ public final String toString() { ); } - /** Standard {@link AutoValue.Builder} for {@link Protocol}. */ + /** + * Default {@link AutoValue.Builder} for {@link Protocol}. + */ @AutoValue.Builder - public static abstract class Builder { + public abstract static class Builder { public abstract Builder setName(String value); diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java deleted file mode 100644 index 0fc57f8967e..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/TestToken.java +++ /dev/null @@ -1,28 +0,0 @@ -package google.registry.monitoring.blackbox; - - -public class TestToken extends Token { - @Override - public Protocol protocol(){ - return Protocol.defaultImplementation(); - } - - @Override - public Token next() { - return this; - } - - @Override - public O message() { - return (O) this.domainName; - } - - @Override - public ActionHandler actionHandler() { - return new ActionHandler(); - } - - public static TestToken generateNext() { - return new TestToken(); - } -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java b/prober/src/main/java/google/registry/monitoring/blackbox/Token.java deleted file mode 100644 index c20ed770888..00000000000 --- a/prober/src/main/java/google/registry/monitoring/blackbox/Token.java +++ /dev/null @@ -1,20 +0,0 @@ -package google.registry.monitoring.blackbox; - -import org.joda.time.Duration; - -abstract class Token { - public static final Duration DEFAULT_DURATION = new Duration(2000L); - protected String domainName; - - abstract Protocol protocol(); - abstract Token next(); - abstract O message(); - abstract ActionHandler actionHandler(); - - private static String newDomainName(String previousName) { - return String.format("prober-%d", System.currentTimeMillis()); - } - - - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 9aa864cc019..3233c1ade5d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -123,7 +123,6 @@ static ImmutableList> providerHttpWhoisHandle messageHandlerProvider, webWhoisActionHandlerProvider); } - /** * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https * protocol. diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java index 57b4bc2f575..b850cfb3b26 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/HttpRequestMessage.java @@ -77,7 +77,8 @@ public HttpRequestMessage modifyMessage(String... args) throws IllegalArgumentEx throw new IllegalArgumentException( String.format( "Wrong number of arguments present for modifying HttpRequestMessage." - + " Received %d arguments instead of: " + Arrays.toString(args), args.length)); + + " Received %d arguments instead of 2. Received arguments: " + + Arrays.toString(args), args.length)); } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java index 1d686e4ec34..0a584dfa2a7 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/InboundMessageType.java @@ -15,7 +15,8 @@ package google.registry.monitoring.blackbox.messages; /** - * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code inboundMessages} in + * channel pipeline */ public interface InboundMessageType { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java index e435ae59f86..4a7c16243cd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/messages/OutboundMessageType.java @@ -17,7 +17,8 @@ import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; /** - * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in channel pipeline + * Marker Interface that is implemented by all classes that serve as {@code outboundMessages} in + * channel pipeline */ public interface OutboundMessageType { diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java index 4c9bfe04fa4..df3296438af 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingActionTest.java @@ -30,13 +30,11 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.nio.NioEventLoopGroup; -import javax.inject.Provider; import org.joda.time.Duration; import org.junit.Ignore; import org.junit.Rule; @@ -71,19 +69,19 @@ public class ProbingActionTest { */ private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); - private Provider testHandlerProvider = () -> testHandler; - private Provider conversionHandlerProvider = () -> conversionHandler; + //TODO - Currently, this test fails to receive outbound messages from the embedded channel, which + // we will fix in a later release. @Ignore @Test - public void testBehavior_existingChannel() { + public void testSuccess_existingChannel() { //setup EmbeddedChannel channel = new EmbeddedChannel(conversionHandler, testHandler); channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture()); // Sets up a Protocol corresponding to when a connection exists. Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(true) @@ -132,13 +130,13 @@ public void testSuccess_newChannel() throws Exception { // Sets up a Protocol corresponding to when a new connection is created. Protocol protocol = Protocol.builder() - .setHandlerProviders(ImmutableList.of(conversionHandlerProvider, testHandlerProvider)) + .setHandlerProviders(ImmutableList.of(() -> conversionHandler, () -> testHandler)) .setName(PROTOCOL_NAME) .setPort(TEST_PORT) .setPersistentConnection(false) .build(); - nettyRule.setUpServer(address, new ChannelInboundHandlerAdapter()); + nettyRule.setUpServer(address); // Sets up a ProbingAction with existing channel using test specified attributes. ProbingAction action = ProbingAction.builder() diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java deleted file mode 100644 index 8f35843cb4c..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestProtocol.java +++ /dev/null @@ -1,70 +0,0 @@ -package google.registry.monitoring.blackbox; - -import static com.google.common.truth.Truth.assertThat; - -import google.registry.monitoring.blackbox.TestModule.TestProtocolModule; -import google.registry.monitoring.blackbox.TestModule.TestComponent; -import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; -import javax.inject.Inject; -import javax.inject.Provider; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Basic unit test for Protocol Class - */ -@RunWith(JUnit4.class) -public class TestProtocol { - - /** - * Stores default values that constitute a Protocol - */ - private static final String HOST_NAME = "127.0.0.1"; - private static final int PORT_NUM = 0; - private static final String NAME = "Test"; - private static final ImmutableList> HANDLERS = ImmutableList.of(); - - /** - * Test Protocol that we build - */ - private Protocol protocol; - - /** - * - * @return Protocol implementation built using fields above - */ - static Protocol defaultImplementation() { - return Protocol.builder() - .host(HOST_NAME) - .port(PORT_NUM) - .name(NAME) - .handlerProviders(HANDLERS) - .build(); - } - - /** - * Stores default implementation into private protocol field - */ - private void basicProtocol() { - protocol = TestProtocol.defaultImplementation(); - } - - - /** - * Basic unit test that insures stored values in protocol are accurate - */ - @Test - public void testProtocolAttributes() { - basicProtocol(); - assertThat(protocol.host()).isEqualTo(HOST_NAME); - assertThat(protocol.port()).isEqualTo(PORT_NUM); - assertThat(protocol.name()).isEqualTo(NAME); - assertThat(protocol.handlerProviders()).isEqualTo(HANDLERS); - } - - - -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java index ad2db4b71d5..4b6eed9c16f 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/NettyRule.java @@ -28,7 +28,7 @@ import google.registry.monitoring.blackbox.ProbingActionTest; import google.registry.monitoring.blackbox.ProbingStepTest; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.testservers.WebWhoisServer; +import google.registry.monitoring.blackbox.testservers.TestServer; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -88,7 +88,7 @@ public void setUpServer(LocalAddress localAddress, ChannelHandler... handlers) { checkState(echoHandler == null, "Can't call setUpServer twice"); echoHandler = new EchoHandler(); - new WebWhoisServer(eventLoopGroup, localAddress, + new TestServer(eventLoopGroup, localAddress, ImmutableList.builder().add(handlers).add(echoHandler).build()); } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index 92d58b429de..d4605327f65 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -22,12 +22,11 @@ import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.ProbingAction; import google.registry.monitoring.blackbox.Protocol; -import google.registry.monitoring.blackbox.testservers.WebWhoisServer; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.messages.HttpResponseMessage; +import google.registry.monitoring.blackbox.testservers.TestServer; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; @@ -112,10 +111,6 @@ private Bootstrap makeBootstrap(EventLoopGroup group) { .channel(LocalChannel.class); } - private void setupLocalServer(String redirectInput, String destinationInput, - EventLoopGroup group, LocalAddress address) { - WebWhoisServer.strippedServer(group, address, redirectInput, destinationInput); - } private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) { msg = new HttpRequestMessage(makeHttpGetRequest(hostName, "")); @@ -183,7 +178,7 @@ public void testBasic_responseFailure_badURL() { channel.writeOutbound(msg); FullHttpResponse response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true, false)); + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true)); //assesses that future listener isn't triggered yet. assertThat(future.isDone()).isFalse(); @@ -215,12 +210,15 @@ public void testAdvanced_redirect() { ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); + // Stores path. + String path = "/test"; + // Sets up the local server that the handler will be redirected to. - setupLocalServer("", host, group, address); + TestServer.webWhoisServer(group, address, "", host, path); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + host, true, false)); + HTTP_REDIRECT + host + path, true)); //checks that future has not been set to successful or a failure assertThat(future.isDone()).isFalse(); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java index 6c3c5feb492..c39fe554390 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java @@ -14,44 +14,39 @@ package google.registry.monitoring.blackbox.testservers; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; +import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; +import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; import com.google.common.collect.ImmutableList; +import google.registry.monitoring.blackbox.messages.HttpResponseMessage; import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; /** * Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to * perform */ -public abstract class TestServer { - private LocalAddress localAddress; +public class TestServer { - TestServer(LocalAddress localAddress, ImmutableList handlers) { + public TestServer(LocalAddress localAddress, ImmutableList handlers) { this(new NioEventLoopGroup(1), localAddress, handlers); } -<<<<<<<< HEAD:prober/src/test/java/google/registry/monitoring/blackbox/testservers/TestServer.java - TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, + public TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { -======== - TestServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, ImmutableList handlers) { - this.localAddress = localAddress; - ->>>>>>>> 949be9b42... Fixed files to pass all style tests:prober/src/test/java/google/registry/monitoring/blackbox/TestServers/TestServer.java //Creates ChannelInitializer with handlers specified ChannelInitializer serverInitializer = new ChannelInitializer() { @Override @@ -72,35 +67,57 @@ protected void initChannel(LocalChannel ch) { ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly(); } + + public static TestServer webWhoisServer(EventLoopGroup eventLoopGroup, + LocalAddress localAddress, String redirectInput, String destinationInput, + String destinationPath) { + return new TestServer( + eventLoopGroup, + localAddress, + ImmutableList.of(new RedirectHandler(redirectInput, destinationInput, destinationPath)) + ); + } + /** - * A handler that echoes back its inbound message. The message is also saved in a promise for - * inspection later. + * Handler that will wither redirect client, give successful response, or give error messge */ - public static class EchoHandler extends ChannelInboundHandlerAdapter { + @Sharable + static class RedirectHandler extends SimpleChannelInboundHandler { - private final CompletableFuture requestFuture = new CompletableFuture<>(); + private String redirectInput; + private String destinationInput; + private String destinationPath; - public Future getRequestFuture() { - return requestFuture; + /** + * @param redirectInput - Server will send back redirect to {@code destinationInput} when + * receiving a request with this host location + * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response + * when receiving a request with this host location + */ + public RedirectHandler(String redirectInput, String destinationInput, String destinationPath) { + this.redirectInput = redirectInput; + this.destinationInput = destinationInput; + this.destinationPath = destinationPath; } + /** + * Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on + * what header location is + */ @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // In the test we only send messages of type ByteBuf. - - assertThat(msg).isInstanceOf(ByteBuf.class); - String request = ((ByteBuf) msg).toString(UTF_8); - // After the message is written back to the client, fulfill the promise. - ChannelFuture unusedFuture = - ctx.writeAndFlush(msg).addListener(f -> requestFuture.complete(request)); - } + public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { + HttpResponse response; + if (request.headers().get("host").equals(redirectInput)) { + response = new HttpResponseMessage( + makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true)); + } else if (request.headers().get("host").equals(destinationInput) + && request.uri().equals(destinationPath)) { + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); + } else { + response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); + } + ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response); - /** Saves any inbound error as the cause of the promise failure. */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ChannelFuture unusedFuture = - ctx.channel().closeFuture().addListener(f -> requestFuture.completeExceptionally(cause)); } } - } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java b/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java deleted file mode 100644 index 238c6a7c0ae..00000000000 --- a/prober/src/test/java/google/registry/monitoring/blackbox/testservers/WebWhoisServer.java +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2019 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.monitoring.blackbox.testservers; - -import static google.registry.monitoring.blackbox.TestUtils.makeHttpResponse; -import static google.registry.monitoring.blackbox.TestUtils.makeRedirectResponse; - -import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.messages.HttpResponseMessage; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandler.Sharable; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.local.LocalAddress; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpServerCodec; - -/** - * {@link TestServer} subtype that performs WebWhois Services Expected - * - *

It will either redirect the client to the correct location if given the - * requisite redirect input, give the client a successful response if they give the expected final - * destination, or give the client an error message if given an unexpected host location

- */ -public class WebWhoisServer extends TestServer { - - public WebWhoisServer(LocalAddress localAddress, - ImmutableList handlers) { - super(localAddress, handlers); - } - - public WebWhoisServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, - ImmutableList handlers) { - super(eventLoopGroup, localAddress, handlers); - } - - /** - * Creates server that doesn't deal with {@link ByteBuf} conversion and just sends the - * HttpRequestMessage object through pipeline - */ - public static WebWhoisServer strippedServer(EventLoopGroup eventLoopGroup, - LocalAddress localAddress, String redirectInput, String destinationInput) { - return new WebWhoisServer( - eventLoopGroup, - localAddress, - ImmutableList.of(new RedirectHandler(redirectInput, destinationInput)) - ); - } - - /** - * Creates server that sends exactly what we expect a remote server to send as a response, by - * sending the {@link ByteBuf} of the response through pipeline - */ - public static WebWhoisServer fullServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress, - String redirectInput, String destinationInput) { - return new WebWhoisServer( - eventLoopGroup, - localAddress, - ImmutableList.of( - new HttpServerCodec(), - new HttpObjectAggregator(1048576), - new RedirectHandler(redirectInput, destinationInput)) - ); - } - - /** - * Handler that will wither redirect client, give successful response, or give error messge - */ - @Sharable - static class RedirectHandler extends SimpleChannelInboundHandler { - - private String redirectInput; - private String destinationInput; - - /** - * @param redirectInput - Server will send back redirect to {@code destinationInput} when - * receiving a request with this host location - * @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response - * when receiving a request with this host location - */ - public RedirectHandler(String redirectInput, String destinationInput) { - this.redirectInput = redirectInput; - this.destinationInput = destinationInput; - } - - /** - * Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on - * what header location is - */ - @Override - public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) { - HttpResponse response; - if (request.headers().get("host").equals(redirectInput)) { - response = new HttpResponseMessage( - makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true)); - } else if (request.headers().get("host").equals(destinationInput)) { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK)); - } else { - response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); - } - ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response); - - } - } -} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index 61d27460f4c..1180f1e83bb 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package google.registry.monitoring.blackbox; +package google.registry.monitoring.blackbox.tokens; import static com.google.common.truth.Truth.assertThat; @@ -25,34 +25,50 @@ import org.junit.runners.JUnit4; /** - * Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) + * Unit Tests for {@link WebWhoisToken} */ @RunWith(JUnit4.class) -public class TokenTest { +public class WebWhoisTokenTest { - private static String PREFIX = "whois.nic."; - private static String TEST_STARTER = "starter"; - private static Iterator TEST_DOMAINS = new DefaultCircularLinkedListIterator.Builder().addElement("test").build(); + private static final String PREFIX = "whois.nic."; + private static final String HOST = "starter"; + private static final String FIRST_TLD = "first_test"; + private static final String SECOND_TLD = "second_test"; + private static final String THIRD_TLD = "third_test"; + private final Iterator TEST_DOMAINS = + new DefaultCircularLinkedListIterator.Builder() + .addElements(FIRST_TLD, SECOND_TLD, THIRD_TLD) + .build(); public Token webToken = new WebWhoisToken(TEST_DOMAINS); @Test - public void testWebToken_MessageModificationSuccess() { + public void testMessageModification() throws UndeterminedStateException { //creates Request message with header HttpRequestMessage message = new HttpRequestMessage(); - message.headers().set("host", TEST_STARTER); + message.headers().set("host", HOST); //attempts to use Token's method for modifying the method based on its stored host - try { - HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); - assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX+TEST_DOMAINS.next()); - } catch(UndeterminedStateException e) { - throw new RuntimeException(e); - } + HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message); + assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX + FIRST_TLD); + } + /** + * As Circular Linked List has not been implemented yet, we cannot yet wrap around, so we don't + * test that in testing {@code next}. + */ + @Test + public void testNextToken() { + assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD); + webToken = webToken.next(); + assertThat(webToken.host()).isEqualTo(PREFIX + SECOND_TLD); + webToken = webToken.next(); + assertThat(webToken.host()).isEqualTo(PREFIX + THIRD_TLD); + webToken = webToken.next(); + assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD); } } diff --git a/settings.gradle b/settings.gradle index da47097cb53..9b2d11de8da 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,17 @@ +// Copyright 2019 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. + if (pluginsUrl) { println "Plugins: Using repo $pluginsUrl..." pluginManagement { @@ -16,10 +30,9 @@ rootProject.name = 'nomulus' include 'core' include 'prober' include 'proxy' +include 'third_party' +include 'util' include 'services:default' include 'services:backend' include 'services:tools' include 'services:pubapi' -include 'third_party' -include 'util' - From b94c4c181617184525b2ba7c1abd7ece65c65811 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 8 Aug 2019 14:41:45 -0400 Subject: [PATCH 332/337] Removed need for TestTokens with Mockito mocks of Tokens --- .../blackbox/AutoValue_NewChannelAction.java | 181 ------------------ .../blackbox/AutoValue_ProbingAction.java | 118 ------------ .../blackbox/AutoValue_Protocol.java | 153 --------------- .../monitoring/blackbox/ProbingAction.java | 45 +++-- .../handlers/WebWhoisActionHandler.java | 4 +- .../monitoring/blackbox/ProbingStepTest.java | 25 ++- .../monitoring/blackbox/TestUtils.java | 60 ------ .../handlers/WebWhoisActionHandlerTest.java | 28 ++- 8 files changed, 61 insertions(+), 553 deletions(-) delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java delete mode 100644 prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java deleted file mode 100644 index 6f818f03a28..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_NewChannelAction.java +++ /dev/null @@ -1,181 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import io.netty.bootstrap.Bootstrap; -import javax.annotation.Generated; -import org.joda.time.Duration; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_NewChannelAction extends NewChannelAction { - - private final Duration delay; - - private final O outboundMessage; - - private final Protocol protocol; - - private final ActionHandler actionHandler; - - private final Bootstrap bootstrap; - - private AutoValue_NewChannelAction( - Duration delay, - O outboundMessage, - Protocol protocol, - ActionHandler actionHandler, - Bootstrap bootstrap) { - this.delay = delay; - this.outboundMessage = outboundMessage; - this.protocol = protocol; - this.actionHandler = actionHandler; - this.bootstrap = bootstrap; - } - - @Override - Duration delay() { - return delay; - } - - @Override - O outboundMessage() { - return outboundMessage; - } - - @Override - Protocol protocol() { - return protocol; - } - - @Override - ActionHandler actionHandler() { - return actionHandler; - } - - @Override - Bootstrap bootstrap() { - return bootstrap; - } - - @Override - public String toString() { - return "NewChannelAction{" - + "delay=" + delay + ", " - + "outboundMessage=" + outboundMessage + ", " - + "protocol=" + protocol + ", " - + "actionHandler=" + actionHandler + ", " - + "bootstrap=" + bootstrap - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof NewChannelAction) { - NewChannelAction that = (NewChannelAction) o; - return this.delay.equals(that.delay()) - && this.outboundMessage.equals(that.outboundMessage()) - && this.protocol.equals(that.protocol()) - && this.actionHandler.equals(that.actionHandler()) - && this.bootstrap.equals(that.bootstrap()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= delay.hashCode(); - h$ *= 1000003; - h$ ^= outboundMessage.hashCode(); - h$ *= 1000003; - h$ ^= protocol.hashCode(); - h$ *= 1000003; - h$ ^= actionHandler.hashCode(); - h$ *= 1000003; - h$ ^= bootstrap.hashCode(); - return h$; - } - - static final class Builder extends NewChannelAction.Builder { - private Duration delay; - private O outboundMessage; - private Protocol protocol; - private ActionHandler actionHandler; - private Bootstrap bootstrap; - Builder() { - } - @Override - public NewChannelAction.Builder delay(Duration delay) { - if (delay == null) { - throw new NullPointerException("Null delay"); - } - this.delay = delay; - return this; - } - @Override - public NewChannelAction.Builder outboundMessage(O outboundMessage) { - if (outboundMessage == null) { - throw new NullPointerException("Null outboundMessage"); - } - this.outboundMessage = outboundMessage; - return this; - } - @Override - public NewChannelAction.Builder protocol(Protocol protocol) { - if (protocol == null) { - throw new NullPointerException("Null protocol"); - } - this.protocol = protocol; - return this; - } - @Override - public NewChannelAction.Builder actionHandler(ActionHandler actionHandler) { - if (actionHandler == null) { - throw new NullPointerException("Null actionHandler"); - } - this.actionHandler = actionHandler; - return this; - } - @Override - public NewChannelAction.Builder bootstrap(Bootstrap bootstrap) { - if (bootstrap == null) { - throw new NullPointerException("Null bootstrap"); - } - this.bootstrap = bootstrap; - return this; - } - @Override - public NewChannelAction build() { - String missing = ""; - if (this.delay == null) { - missing += " delay"; - } - if (this.outboundMessage == null) { - missing += " outboundMessage"; - } - if (this.protocol == null) { - missing += " protocol"; - } - if (this.actionHandler == null) { - missing += " actionHandler"; - } - if (this.bootstrap == null) { - missing += " bootstrap"; - } - if (!missing.isEmpty()) { - throw new IllegalStateException("Missing required properties:" + missing); - } - return new AutoValue_NewChannelAction( - this.delay, - this.outboundMessage, - this.protocol, - this.actionHandler, - this.bootstrap); - } - } - -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java deleted file mode 100644 index 26f560b145b..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_ProbingAction.java +++ /dev/null @@ -1,118 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import io.netty.channel.Channel; -import javax.annotation.Generated; -import org.joda.time.Duration; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_ProbingAction extends ProbingAction { - - private final Duration delay; - - private final O outboundMessage; - - private final Channel channel; - - private final Protocol protocol; - - private final ActionHandler actionHandler; - - AutoValue_ProbingAction( - Duration delay, - O outboundMessage, - Channel channel, - Protocol protocol, - ActionHandler actionHandler) { - if (delay == null) { - throw new NullPointerException("Null delay"); - } - this.delay = delay; - if (outboundMessage == null) { - throw new NullPointerException("Null outboundMessage"); - } - this.outboundMessage = outboundMessage; - if (channel == null) { - throw new NullPointerException("Null channel"); - } - this.channel = channel; - if (protocol == null) { - throw new NullPointerException("Null protocol"); - } - this.protocol = protocol; - if (actionHandler == null) { - throw new NullPointerException("Null actionHandler"); - } - this.actionHandler = actionHandler; - } - - @Override - Duration delay() { - return delay; - } - - @Override - O outboundMessage() { - return outboundMessage; - } - - @Override - Channel channel() { - return channel; - } - - @Override - Protocol protocol() { - return protocol; - } - - @Override - ActionHandler actionHandler() { - return actionHandler; - } - - @Override - public String toString() { - return "ProbingAction{" - + "delay=" + delay + ", " - + "outboundMessage=" + outboundMessage + ", " - + "channel=" + channel + ", " - + "protocol=" + protocol + ", " - + "actionHandler=" + actionHandler - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof ProbingAction) { - ProbingAction that = (ProbingAction) o; - return this.delay.equals(that.delay()) - && this.outboundMessage.equals(that.outboundMessage()) - && this.channel.equals(that.channel()) - && this.protocol.equals(that.protocol()) - && this.actionHandler.equals(that.actionHandler()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= delay.hashCode(); - h$ *= 1000003; - h$ ^= outboundMessage.hashCode(); - h$ *= 1000003; - h$ ^= channel.hashCode(); - h$ *= 1000003; - h$ ^= protocol.hashCode(); - h$ *= 1000003; - h$ ^= actionHandler.hashCode(); - return h$; - } - -} diff --git a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java b/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java deleted file mode 100644 index 3247cbdd310..00000000000 --- a/prober/out/production/classes/generated/google/registry/monitoring/blackbox/AutoValue_Protocol.java +++ /dev/null @@ -1,153 +0,0 @@ - - -package google.registry.monitoring.blackbox; - -import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelHandler; -import javax.annotation.Generated; -import javax.inject.Provider; - -@Generated("com.google.auto.value.processor.AutoValueProcessor") -final class AutoValue_Protocol extends Protocol { - - private final String name; - - private final int port; - - private final String host; - - private final ImmutableList> handlerProviders; - - private AutoValue_Protocol( - String name, - int port, - String host, - ImmutableList> handlerProviders) { - this.name = name; - this.port = port; - this.host = host; - this.handlerProviders = handlerProviders; - } - - @Override - String name() { - return name; - } - - @Override - int port() { - return port; - } - - @Override - String host() { - return host; - } - - @Override - ImmutableList> handlerProviders() { - return handlerProviders; - } - - @Override - public String toString() { - return "Protocol{" - + "name=" + name + ", " - + "port=" + port + ", " - + "host=" + host + ", " - + "handlerProviders=" + handlerProviders - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof Protocol) { - Protocol that = (Protocol) o; - return this.name.equals(that.name()) - && this.port == that.port() - && this.host.equals(that.host()) - && this.handlerProviders.equals(that.handlerProviders()); - } - return false; - } - - @Override - public int hashCode() { - int h$ = 1; - h$ *= 1000003; - h$ ^= name.hashCode(); - h$ *= 1000003; - h$ ^= port; - h$ *= 1000003; - h$ ^= host.hashCode(); - h$ *= 1000003; - h$ ^= handlerProviders.hashCode(); - return h$; - } - - static final class Builder extends Protocol.Builder { - private String name; - private Integer port; - private String host; - private ImmutableList> handlerProviders; - Builder() { - } - @Override - Protocol.Builder name(String name) { - if (name == null) { - throw new NullPointerException("Null name"); - } - this.name = name; - return this; - } - @Override - Protocol.Builder port(int port) { - this.port = port; - return this; - } - @Override - Protocol.Builder host(String host) { - if (host == null) { - throw new NullPointerException("Null host"); - } - this.host = host; - return this; - } - @Override - Protocol.Builder handlerProviders(ImmutableList> handlerProviders) { - if (handlerProviders == null) { - throw new NullPointerException("Null handlerProviders"); - } - this.handlerProviders = handlerProviders; - return this; - } - @Override - Protocol build() { - String missing = ""; - if (this.name == null) { - missing += " name"; - } - if (this.port == null) { - missing += " port"; - } - if (this.host == null) { - missing += " host"; - } - if (this.handlerProviders == null) { - missing += " handlerProviders"; - } - if (!missing.isEmpty()) { - throw new IllegalStateException("Missing required properties:" + missing); - } - return new AutoValue_Protocol( - this.name, - this.port, - this.host, - this.handlerProviders); - } - } - -} diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 36413b73452..8173ba6baee 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -42,7 +42,6 @@ import java.net.UnknownHostException; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import javax.inject.Provider; import org.joda.time.Duration; @@ -117,11 +116,20 @@ private static void addHandlers( * {@link Channel} object that either created by or passed into this {@link ProbingAction} * instance */ - @Nullable public abstract Channel channel(); /** - * Performs the work of the actual action + * The {@link Protocol} instance that specifies type of connection + */ + public abstract Protocol protocol(); + + /** + * The hostname of the remote host we have a connection or will make a connection to + */ + public abstract String host(); + + /** + * Performs the work of the actual action. * *

First, checks if channel is active by setting a listener to perform the bulk of the work * when the connection future is successful.

@@ -136,21 +144,6 @@ private static void addHandlers( * * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ - - /** - * The {@link Protocol} instance that specifies type of connection - */ - public abstract Protocol protocol(); - - /** - * The hostname of the remote host we have a connection or will make a connection to - */ - public abstract String host(); - - /** - * Method that calls on {@code performAction} when it is certain channel connection is - * established. - */ @Override public ChannelFuture call() { //ChannelPromise that we return @@ -180,7 +173,8 @@ public ChannelFuture call() { timer.newTimeout(timeout -> { // Write appropriate outboundMessage to pipeline - ChannelFuture unusedflushFuture = channel().writeAndFlush(outboundMessage()); + ChannelFuture unusedFutureWriteAndFlush = + channel().writeAndFlush(outboundMessage()); channelFuture.addListeners( future -> { if (future.isSuccess()) { @@ -272,6 +266,7 @@ public Builder setBootstrap(Bootstrap bootstrap) { abstract ProbingAction autoBuild(); public ProbingAction build() { + // Sets SocketAddress to bind to. SocketAddress address; try { InetAddress hostAddress = InetAddress.getByName(host()); @@ -280,12 +275,20 @@ public ProbingAction build() { address = new LocalAddress(host()); } - checkArgument(channel() == null ^ bootstrap == null, + //Sets channel supplied or to be created. + Channel channel; + try { + channel = channel(); + } catch (IllegalStateException e) { + channel = null; + } + + checkArgument(channel == null ^ bootstrap == null, "One and only one of bootstrap and channel must be supplied."); //If a channel is supplied, nothing is needed to be done //Otherwise, a Bootstrap must be supplied and be used for creating the channel - if (channel() == null) { + if (channel == null) { bootstrap.handler( new ChannelInitializer() { @Override diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java index c0f7ce8ae78..c56c8c7d97c 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandler.java @@ -101,7 +101,9 @@ public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg) //On success, we always pass message to ActionHandler's channelRead0 method. super.channelRead0(ctx, msg); - } else if (response.headers().get("location") != null) { + } else if (response.status().equals(HttpResponseStatus.MOVED_PERMANENTLY) + || response.status().equals(HttpResponseStatus.FOUND)) { + //TODO - Fix checker to better determine when we have encountered a redirection response. //Obtain url to be redirected to URL url; diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java index 81c7e31ce95..132f19f8b48 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingStepTest.java @@ -16,15 +16,17 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.monitoring.blackbox.ProbingAction.CONNECTION_FUTURE_KEY; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import com.google.common.collect.ImmutableList; -import google.registry.monitoring.blackbox.TestUtils.ExistingChannelToken; -import google.registry.monitoring.blackbox.TestUtils.NewChannelToken; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.handlers.ActionHandler; import google.registry.monitoring.blackbox.handlers.ConversionHandler; import google.registry.monitoring.blackbox.handlers.NettyRule; import google.registry.monitoring.blackbox.handlers.TestActionHandler; +import google.registry.monitoring.blackbox.messages.OutboundMessageType; import google.registry.monitoring.blackbox.messages.TestMessage; import google.registry.monitoring.blackbox.tokens.Token; import io.netty.bootstrap.Bootstrap; @@ -38,6 +40,7 @@ import org.joda.time.Duration; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; /** * Unit Tests for {@link ProbingSequence}s and {@link ProbingStep}s and their specific @@ -72,6 +75,19 @@ public class ProbingStepTest { private ActionHandler testHandler = new TestActionHandler(); private ChannelHandler conversionHandler = new ConversionHandler(); + /** + * Creates mock {@link Token} object that returns the host and returns unchanged message when + * modifying it. + */ + private Token testToken(String host) throws UndeterminedStateException { + Token token = Mockito.mock(Token.class); + doReturn(host).when(token).host(); + doAnswer(answer -> ((OutboundMessageType) answer.getArgument(0)).modifyMessage(host)) + .when(token) + .modifyMessage(any(OutboundMessageType.class)); + + return token; + } @Test public void testProbingActionGenerate_embeddedChannel() throws UndeterminedStateException { @@ -89,7 +105,8 @@ public void testProbingActionGenerate_embeddedChannel() throws UndeterminedState // Sets up testToken to return arbitrary value, and the embedded channel. Used for when the // ProbingStep generates an ExistingChannelAction. - Token testToken = new ExistingChannelToken(channel, SECONDARY_TEST_MESSAGE); + Token testToken = testToken(SECONDARY_TEST_MESSAGE); + doReturn(channel).when(testToken).channel(); // Sets up generic {@link ProbingStep} that we are testing. ProbingStep testStep = ProbingStep.builder() @@ -130,7 +147,7 @@ public void testProbingActionGenerate_newChannel() throws UndeterminedStateExcep // Sets up testToken to return arbitrary values, and no channel. Used when we create a new // channel. - Token testToken = new NewChannelToken(ADDRESS_NAME); + Token testToken = testToken(ADDRESS_NAME); // Sets up server listening at LocalAddress so generated action can have successful connection. nettyRule.setUpServer(address); diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java index e18c853a3f0..66e2928f45e 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/TestUtils.java @@ -16,12 +16,8 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; -import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import google.registry.monitoring.blackbox.tokens.Token; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -70,61 +66,5 @@ public static FullHttpResponse makeRedirectResponse( } return response; } - - /** - * Basic outline for {@link Token} instances to be used in tests - */ - abstract static class TestToken extends Token { - - protected String host; - - protected TestToken(String host) { - this.host = host; - } - - @Override - public Token next() { - return this; - } - - @Override - public OutboundMessageType modifyMessage(OutboundMessageType message) - throws UndeterminedStateException { - return message.modifyMessage(host); - } - - @Override - public String host() { - return host; - } - - } - - /** - * {@link TestToken} instance that creates new channel - */ - public static class NewChannelToken extends TestToken { - - public NewChannelToken(String host) { - super(host); - } - - @Override - public Channel channel() { - return null; - } - } - - /** - * {@link TestToken} instance that passes in existing channel - */ - public static class ExistingChannelToken extends TestToken { - - - public ExistingChannelToken(Channel channel, String host) { - super(host); - this.channel = channel; - } - } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java index d4605327f65..a4c2c57dc1a 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/handlers/WebWhoisActionHandlerTest.java @@ -55,7 +55,7 @@ public class WebWhoisActionHandlerTest { private static final String HTTP_REDIRECT = "http://"; private static final String TARGET_HOST = "whois.nic.tld"; private static final String DUMMY_URL = "__WILL_NOT_WORK__"; - private final Protocol STANDARD_PROTOCOL = Protocol.builder() + private final Protocol standardProtocol = Protocol.builder() .setHandlerProviders(ImmutableList.of(() -> new WebWhoisActionHandler( null, null, null, null))) .setName("http") @@ -89,8 +89,8 @@ private Protocol createProtocol(String name, int port, boolean persistentConnect private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) { actionHandler = new WebWhoisActionHandler( bootstrap, - STANDARD_PROTOCOL, - STANDARD_PROTOCOL, + standardProtocol, + standardProtocol, messageTemplate ); actionHandlerProvider = () -> actionHandler; @@ -146,27 +146,26 @@ public void testBasic_responseFailure_badRequest() { setup("", null, false); setupChannel(initialProtocol); - //stores future + // Stores future that informs when action is completed. ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); FullHttpResponse response = new HttpResponseMessage( makeHttpResponse(HttpResponseStatus.BAD_REQUEST)); - //assesses that future listener isn't triggered yet. + // Assesses that future listener isn't triggered yet. assertThat(future.isDone()).isFalse(); channel.writeInbound(response); - //assesses that listener is triggered, but event is not success + // Assesses that listener is triggered, but event is not success assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same + // Ensures that we fail as a result of a FailureException. assertThat(future.cause() instanceof FailureException).isTrue(); } - @SuppressWarnings("CheckReturnValue") @Test public void testBasic_responseFailure_badURL() { //setup @@ -189,8 +188,8 @@ public void testBasic_responseFailure_badURL() { assertThat(future.isDone()).isTrue(); assertThat(future.isSuccess()).isFalse(); - //ensures Protocol is the same - assertThat(future.cause() instanceof FailureException); + // Ensures that we fail as a result of a FailureException. + assertThat(future.cause() instanceof FailureException).isTrue(); } @Test @@ -203,22 +202,21 @@ public void testAdvanced_redirect() { setupChannel(initialProtocol); // Initializes LocalAddress with unique String. - String host = TARGET_HOST + System.currentTimeMillis(); - LocalAddress address = new LocalAddress(host); + LocalAddress address = new LocalAddress(TARGET_HOST); //stores future ChannelFuture future = actionHandler.getFinishedFuture(); channel.writeOutbound(msg); - // Stores path. + // Path that we test WebWhoisActionHandler uses. String path = "/test"; // Sets up the local server that the handler will be redirected to. - TestServer.webWhoisServer(group, address, "", host, path); + TestServer.webWhoisServer(group, address, "", TARGET_HOST, path); FullHttpResponse response = new HttpResponseMessage(makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, - HTTP_REDIRECT + host + path, true)); + HTTP_REDIRECT + TARGET_HOST + path, true)); //checks that future has not been set to successful or a failure assertThat(future.isDone()).isFalse(); From 58a0c18efd7352a08549f195c025f81cdf48bda0 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Thu, 8 Aug 2019 16:00:49 -0400 Subject: [PATCH 333/337] Fixed style issues in DefaultCircularLinkedListIterator and AbstractCircularLinkedListIterator --- .../AbstractCircularLinkedListIterator.java | 157 ++++++++++++------ .../DefaultCircularLinkedListIterator.java | 27 ++- 2 files changed, 121 insertions(+), 63 deletions(-) diff --git a/util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java b/util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java index 9452c053cef..432fc659edf 100644 --- a/util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java +++ b/util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java @@ -19,91 +19,133 @@ import java.util.Iterator; /** - * Immutable class that support circular iteration through a group of elements of type {@param }. + * Immutable class that support circular iteration through a group of elements of type {@param + * }. * * @param - Element type stored in the iterator * *

Is an immutable object that, when built, creates a circular pointing - * group of Entries, that allows for looped iteration. The first and last - * element in the closed loop are also stored.

+ * group of Entries, that allows for looped iteration. The first and last element in the closed loop + * are also stored.

*/ public abstract class AbstractCircularLinkedListIterator implements Iterator { - /** First {@link Entry} in the circular iterator. */ + /** + * First {@link Entry} in the circular iterator. + */ private final Entry first; - /** Last {@link Entry} in the circular iterator. */ + /** + * Last {@link Entry} in the circular iterator. + */ private final Entry last; - /** Current {@link Entry} in iterator. */ + /** + * Current {@link Entry} in iterator. + */ private Entry current; - /** Because this is a circular linked list iterator, there is always a next element. */ + /** + * After having established pointers between {@link Entry}s, sets first element to the first + * {@link Entry} added to {@link Builder} and sets last element to last one added to {@link + * Builder}. + */ + protected AbstractCircularLinkedListIterator(Entry first, Entry last) { + checkNotNull(last.next); + this.first = first; + this.last = last; + } + + /** + * Because this is a circular linked list iterator, there is always a next element. + */ @Override public boolean hasNext() { return true; } - /** Obtains the next element by calling on the {@link Entry}'s next element. */ + /** + * Obtains the next element by calling on the {@link Entry}'s next element. + */ @Override public T next() { - if (current == null) - //If this is first call of next, return first element + if (current == null) { + //If this is first call of next, return first element + current = first; - else - //Otherwise return element after current element + } else { + //Otherwise return element after current element + current = current.next; + } return current.data; } - /** Get method for current element in iterator. */ + /** + * Get method for current element in iterator. + */ public T get() { - if (current == null) - //if we have not started iterating, there is no current Entry, so return null + if (current == null) { + //if we have not started iterating, there is no current Entry, so return null return null; - else - //otherwise, retrieve the current Entry's data + + } else { + //otherwise, retrieve the current Entry's data return current.data; + } } - /** Returns stored first element. */ + /** + * Returns stored first element. + */ public T getFirst() { return first.data; } - /** Returns stored last element. */ + /** + * Returns stored last element. + */ public T getLast() { return last.data; } /** - * Node class for {@link AbstractCircularLinkedListIterator} that stores value of element - * and points to next {@link Entry}. + * Node class for {@link AbstractCircularLinkedListIterator} that stores value of element and + * points to next {@link Entry}. * * @param - Matching element type of iterator. */ protected static class Entry { - /** Stores the {@param } instance. */ + + /** + * Stores the {@param } instance. + */ T data; - /** Saves reference to next {@link Entry} in iterator. */ + /** + * Saves reference to next {@link Entry} in iterator. + */ Entry next; - /** Necessary for setting next {@link Entry} for subclasses outside of current package. */ - public void setNext(Entry next) { - this.next = next; - } - - /** Only needs {@param } instance for initialization. */ + /** + * Only needs {@param } instance for initialization. + */ Entry(T data) { this.data = data; } + + /** + * Necessary for setting next {@link Entry} for subclasses outside of current package. + */ + public void setNext(Entry next) { + this.next = next; + } } /** - * As {@link AbstractCircularLinkedListIterator} is an immutable class, it needs - * a builder for instantiation. + * As {@link AbstractCircularLinkedListIterator} is an immutable class, it needs a builder for + * instantiation. * * @param - Matching element type of iterator * @@ -113,61 +155,66 @@ public void setNext(Entry next) { *

Sets first element added to {@code first}, and when built, sets last added * element to {@code last} and points it to the {@code first} element.

*/ - public abstract static class Builder, L extends AbstractCircularLinkedListIterator> { - /** Matching first entry in the circular iterator to be built. */ + public abstract static class Builder, + L extends AbstractCircularLinkedListIterator> { + + /** + * Matching first entry in the circular iterator to be built. + */ protected Entry first; - /** {@link Entry} corresponding to most recent element added. */ + /** + * {@link Entry} corresponding to most recent element added. + */ protected Entry current; - /** Sets current {@link Entry} to element added and points previous {@link Entry} to this one. */ + /** + * Sets current {@link Entry} to element added and points previous {@link Entry} to this one. + */ public Builder addElement(T element) { Entry nextEntry = new Entry<>(element); - if (current == null) - //If this is first element added, we set it to first + if (current == null) { + //If this is first element added, we set it to first first = nextEntry; - else - //Otherwise point previous Entry to this one + } else { + //Otherwise point previous Entry to this one current.next = nextEntry; + } current = nextEntry; return this; } - /** Simply calls {@code addElement}, for each element in {@code elements}. */ + /** + * Simply calls {@code addElement}, for each element in {@code elements}. + */ public Builder addElements(Iterable elements) { elements.forEach(this::addElement); return this; } - /** Simply calls {@code addElement}, for each element in {@code elements}. */ + /** + * Simply calls {@code addElement}, for each element in {@code elements}. + */ public Builder addElements(T... elements) { - for (T element : elements) + for (T element : elements) { addElement(element); + } return this; } /** - * Converts {@link Builder} to input subclass. + * Converts {@link Builder} to input subclass. * *

Necessary for applying custom build methods when constructing * subclasses that are inherent to the attributes of those subclasses.

*/ public abstract B childBuilder(); - /** Points last {@link Entry} to first {@link Entry}, and calls private constructor. */ + /** + * Points last {@link Entry} to first {@link Entry}, and calls private constructor. + */ public abstract L build(); } - - /** - * After having established pointers between {@link Entry}s, sets - * first element to the first {@link Entry} added to {@link Builder} - * and sets last element to last one added to {@link Builder}. - */ - protected AbstractCircularLinkedListIterator(Entry first, Entry last) { - checkNotNull(last.next); - this.first = first; - this.last = last; - } } diff --git a/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java b/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java index 367feafde11..850773a8f08 100644 --- a/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java +++ b/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java @@ -15,30 +15,41 @@ package google.registry.util; /** - * Default implementation of {@link AbstractCircularLinkedListIterator} with generic type - * {@param } that operates only in closed circular loop. + * Default implementation of {@link AbstractCircularLinkedListIterator} with generic type {@param + * } that operates only in closed circular loop. * * @param - Type of elements in iterator. - * */ public class DefaultCircularLinkedListIterator extends AbstractCircularLinkedListIterator { - public static class Builder extends AbstractCircularLinkedListIterator.Builder, DefaultCircularLinkedListIterator> { + private DefaultCircularLinkedListIterator(Entry first, Entry last) { + super(first, last); + } + + /** + * {@link Builder} for {@link DefaultCircularLinkedListIterator}. + * + *

Doesn't do anything different than {@link AbstractCircularLinkedListIterator.Builder} but + * implementation of {@code childBuilder} and actual {@code build} methods.

+ * + */ + public static class Builder extends + AbstractCircularLinkedListIterator.Builder, + DefaultCircularLinkedListIterator> { @Override public Builder childBuilder() { return this; } - /** On build, close loop by pointing last element to first. */ + /** + * On build, close loop by pointing last element to first. + */ @Override public DefaultCircularLinkedListIterator build() { current.setNext(first); return new DefaultCircularLinkedListIterator<>(first, current); } } - private DefaultCircularLinkedListIterator(Entry first, Entry last) { - super(first, last); - } } From 6f3974300e8fa9110a935883e8b4d6cee99ac93b Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 9 Aug 2019 12:21:53 -0400 Subject: [PATCH 334/337] Modified CircularList according to changes suggested by jianglai. --- .../monitoring/blackbox/ProbingAction.java | 8 +- .../monitoring/blackbox/ProbingSequence.java | 112 ++++++--- .../monitoring/blackbox/ProbingStep.java | 5 +- .../monitoring/blackbox/WebWhoisModule.java | 16 +- .../exceptions/ConnectionException.java | 4 +- .../UndeterminedStateException.java | 5 +- .../blackbox/tokens/WebWhoisToken.java | 20 +- .../blackbox/ProbingSequenceTest.java | 61 +++-- .../blackbox/tokens/WebWhoisTokenTest.java | 11 +- .../AbstractCircularLinkedListIterator.java | 220 ------------------ .../google/registry/util/CircularList.java | 146 ++++++++++++ .../DefaultCircularLinkedListIterator.java | 55 ----- 12 files changed, 289 insertions(+), 374 deletions(-) delete mode 100644 util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java create mode 100644 util/src/main/java/google/registry/util/CircularList.java delete mode 100644 util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java index 8173ba6baee..bfda982329e 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingAction.java @@ -135,12 +135,12 @@ private static void addHandlers( * when the connection future is successful.

* *

Once the connection is successful, we establish which of the handlers in the pipeline is - * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when - * we receive an expected response from the server.

+ * the {@link ActionHandler}.From that, we can obtain a future that is marked as a success when we + * receive an expected response from the server.

* *

Next, we set a timer set to a specified delay. After the delay has passed, we send the - * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, - * we inform the {@link ProbingStep} of this.

+ * {@code outboundMessage} down the channel pipeline, and when we observe a success or failure, we + * inform the {@link ProbingStep} of this.

* * @return {@link ChannelFuture} that denotes when the action has been successfully performed. */ diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 69043665d16..a8d4008c1ee 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -17,7 +17,7 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.tokens.Token; -import google.registry.util.AbstractCircularLinkedListIterator; +import google.registry.util.CircularList; import io.netty.bootstrap.Bootstrap; import io.netty.channel.AbstractChannel; import io.netty.channel.ChannelFuture; @@ -26,9 +26,9 @@ /** * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - *

Inherits from {@link AbstractCircularLinkedListIterator}

, with element type of + *

Inherits from {@link CircularList}

, with element type of * {@link ProbingStep} as the manner in which the sequence is carried out is analogous to the {@link - * AbstractCircularLinkedListIterator} + * CircularList} * * *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} @@ -39,7 +39,7 @@ * the first one is activated with the requisite {@link Token}, the {@link ProbingStep}s do the rest * of the work.

*/ -public class ProbingSequence extends AbstractCircularLinkedListIterator { +public class ProbingSequence extends CircularList { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); @@ -48,11 +48,42 @@ public class ProbingSequence extends AbstractCircularLinkedListIterator first, Entry last, Token startToken) { - super(first, last); + /** + * Each {@link ProbingSequence} is considered to not be the last step unless specified by the + * {@link Builder}. + */ + private boolean lastStep = false; + + /** + * Standard constructor for {@link ProbingSequence} that assigns value to the node. + */ + private ProbingSequence(ProbingStep value) { + super(value); + } + + /** + * Constructor for first {@link ProbingSequence} in the list that assigns value and token. + */ + private ProbingSequence(ProbingStep value, Token startToken) { + this(value); this.startToken = startToken; } + /** + * Method used in {@link Builder} to mark the last step in the sequence. + */ + private void markLast() { + lastStep = true; + } + + /** + * Obtains next {@link ProbingSequence} in sequence instead of next {@link CircularList}. + */ + @Override + public ProbingSequence next() { + return (ProbingSequence) super.next(); + } + /** * Starts ProbingSequence by calling first {@code runStep} with {@code startToken}. */ @@ -67,8 +98,8 @@ public void start() { * @param token - used to generate the {@link ProbingAction} by calling {@code * get().generateAction}. * - *

Moves on to next {@link ProbingStep} in the iterator and changes the {@link Token} - * to the next one if the previous step was the last one in the loop.

+ *

Calls {@code runNextStep} to have next {@link ProbingSequence} call {@code runStep} + * with next token depending on if the current step is the last one in the sequence. * *

If unable to generate the action, or the calling the action results in an immediate error, * we note an error. Otherwise, if the future marked as finished when the action is completed is @@ -76,23 +107,13 @@ public void start() { * failure or error.

*/ private void runStep(Token token) { - Token finalToken; - if (get() == getLast()) { - finalToken = token.next(); - } else { - finalToken = token; - } - - //Calls next runStep - next(); - ProbingAction currentAction; //attempt to generate new action. On error, move on to next step try { - currentAction = get().generateAction(finalToken); + currentAction = get().generateAction(token); } catch (UndeterminedStateException e) { logger.atWarning().withCause(e).log("Error in Action Generation"); - runStep(finalToken); + runNextStep(token); return; } @@ -105,7 +126,7 @@ private void runStep(Token token) { logger.atWarning().withCause(e).log("Error in Action Performed"); //Calls next runStep - runStep(finalToken); + runNextStep(token); return; } @@ -120,26 +141,35 @@ private void runStep(Token token) { } if (get().protocol().persistentConnection()) { - //If the connection is persistent, we store the channel in the token + //If the connection is persistent, we store the channel in the token - finalToken.setChannel(currentAction.channel()); + token.setChannel(currentAction.channel()); } //Calls next runStep - runStep(finalToken); + runNextStep(token); }); } + /** + * Helper method to first generate the next token, then call runStep on the next {@link + * ProbingSequence}. + */ + private void runNextStep(Token token) { + token = lastStep ? token.next() : token; + next().runStep(token); + + } + /** * Turns {@link ProbingStep.Builder}s into fully self-dependent sequence with supplied {@link * Bootstrap}. */ - public static class Builder extends AbstractCircularLinkedListIterator.Builder { + public static class Builder extends CircularList.AbstractBuilder { - private Entry firstRepeatedStepEntry; + private ProbingSequence firstRepeatedSequenceStep; private Token startToken; @@ -155,30 +185,38 @@ public Builder(Token startToken) { * We take special note of the first repeated step. */ public Builder markFirstRepeated() { - firstRepeatedStepEntry = current; + firstRepeatedSequenceStep = current; return this; } - /** - * Returns this builder as childBuilder. - */ @Override - public Builder childBuilder() { + public Builder add(ProbingStep value) { + super.add(value); return this; } + @Override + protected ProbingSequence create(ProbingStep value) { + if (first == null) { + return new ProbingSequence(value, startToken); + } else { + return new ProbingSequence(value); + } + } + /** - * Points last {@link ProbingStep} to the {@code firstRepeatedStep} and calls private + * Points last {@link ProbingStep} to the {@code firstRepeatedSequenceStep} and calls private * constructor to create {@link ProbingSequence}. */ @Override public ProbingSequence build() { - if (firstRepeatedStepEntry == null) { - firstRepeatedStepEntry = first; + if (firstRepeatedSequenceStep == null) { + firstRepeatedSequenceStep = first; } - current.setNext(firstRepeatedStepEntry); - return new ProbingSequence(first, current, startToken); + current.markLast(); + current.setNext(firstRepeatedSequenceStep); + return first; } } } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java index 58414c1524c..614e6740341 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingStep.java @@ -86,7 +86,9 @@ public final String toString() { messageTemplate().getClass().getName()); } - /** Standard {@link AutoValue.Builder} for {@link ProbingStep}. */ + /** + * Standard {@link AutoValue.Builder} for {@link ProbingStep}. + */ @AutoValue.Builder public abstract static class Builder { @@ -100,6 +102,5 @@ public abstract static class Builder { public abstract ProbingStep build(); } - } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java index 3233c1ade5d..c7d6714e418 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/WebWhoisModule.java @@ -23,7 +23,7 @@ import google.registry.monitoring.blackbox.handlers.WebWhoisMessageHandler; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; import google.registry.monitoring.blackbox.tokens.WebWhoisToken; -import google.registry.util.DefaultCircularLinkedListIterator; +import google.registry.util.CircularList; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; @@ -32,7 +32,6 @@ import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.ssl.SslProvider; -import java.util.Iterator; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; @@ -50,8 +49,8 @@ public class WebWhoisModule { * Standard length of messages used by Proxy. Equates to 0.5 MB. */ private static final int maximumMessageLengthBytes = 512 * 1024; - private final int HTTP_WHOIS_PORT = 80; - private final int HTTPS_WHOIS_PORT = 443; + private static final int HTTP_WHOIS_PORT = 80; + private static final int HTTPS_WHOIS_PORT = 443; /** * {@link Provides} only step used in WebWhois sequence. @@ -123,6 +122,7 @@ static ImmutableList> providerHttpWhoisHandle messageHandlerProvider, webWhoisActionHandlerProvider); } + /** * {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https * protocol. @@ -189,7 +189,7 @@ ProbingSequence provideWebWhoisSequence( WebWhoisToken webWhoisToken) { return new ProbingSequence.Builder(webWhoisToken) - .addElement(probingStep) + .add(probingStep) .build(); } @@ -205,9 +205,9 @@ int provideMaximumMessageLengthBytes() { @Singleton @Provides @WebWhoisProtocol - Iterator provideTopLevelDomains() { - return new DefaultCircularLinkedListIterator.Builder() - .addElements("how", "soy", "xn--q9jyb4c") + CircularList provideTopLevelDomains() { + return new CircularList.Builder() + .add("how", "soy", "xn--q9jyb4c") .build(); } diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java index adb833ec629..776a231d6dd 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/ConnectionException.java @@ -15,8 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Subclass of {@link UndeterminedStateException} that represents all instances when - * the action performed failed due to an issue in the connection with the server. + * Subclass of {@link UndeterminedStateException} that represents all instances when the action + * performed failed due to an issue in the connection with the server. */ public class ConnectionException extends UndeterminedStateException { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java index c155d695c7f..d7127717d52 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UndeterminedStateException.java @@ -15,9 +15,8 @@ package google.registry.monitoring.blackbox.exceptions; /** - * Base exception class for all instances when the action performed fails - * before we can determine the state of the result, meaning the status - * is recorded as ERROR. + * Base exception class for all instances when the action performed fails before we can determine + * the state of the result, meaning the status is recorded as ERROR. */ public class UndeterminedStateException extends Exception { diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java index 6c41c028df1..91160f5c667 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/tokens/WebWhoisToken.java @@ -18,7 +18,7 @@ import google.registry.monitoring.blackbox.WebWhoisModule.WebWhoisProtocol; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.OutboundMessageType; -import java.util.Iterator; +import google.registry.util.CircularList; import javax.inject.Inject; /** @@ -38,26 +38,20 @@ public class WebWhoisToken extends Token { /** * {@link ImmutableList} of all top level domains to be probed. */ - private final Iterator topLevelDomainsIterator; - - /** - * Current index of {@code topLevelDomains} that represents tld we are probing. - */ - private String currentDomain; + private CircularList topLevelDomainsList; @Inject - public WebWhoisToken(@WebWhoisProtocol Iterator topLevelDomainsIterator) { + public WebWhoisToken(@WebWhoisProtocol CircularList topLevelDomainsList) { - this.topLevelDomainsIterator = topLevelDomainsIterator; - currentDomain = this.topLevelDomainsIterator.next(); + this.topLevelDomainsList = topLevelDomainsList; } /** - * Increments {@code domainsIndex} or resets it to reflect move to next top level domain. + * Moves on to next top level domain in {@code topLevelDomainsList}. */ @Override public WebWhoisToken next() { - currentDomain = topLevelDomainsIterator.next(); + topLevelDomainsList = topLevelDomainsList.next(); return this; } @@ -76,7 +70,7 @@ public OutboundMessageType modifyMessage(OutboundMessageType original) */ @Override public String host() { - return PREFIX + currentDomain; + return PREFIX + topLevelDomainsList.get(); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index fe92660dbeb..c215365e4f1 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -19,6 +19,8 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; @@ -82,15 +84,21 @@ public void testSequenceBasicConstruction_Success() { ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addElement(firstStep) - .addElement(secondStep) - .addElement(thirdStep) + .add(firstStep) + .add(secondStep) + .add(thirdStep) .build(); - assertThat(sequence.next()).isEqualTo(firstStep); - assertThat(sequence.next()).isEqualTo(secondStep); - assertThat(sequence.next()).isEqualTo(thirdStep); - assertThat(sequence.next()).isEqualTo(firstStep); + assertThat(sequence.get()).isEqualTo(firstStep); + sequence = sequence.next(); + + assertThat(sequence.get()).isEqualTo(secondStep); + sequence = sequence.next(); + + assertThat(sequence.get()).isEqualTo(thirdStep); + sequence = sequence.next(); + + assertThat(sequence.get()).isEqualTo(firstStep); } @Test @@ -100,17 +108,22 @@ public void testSequenceAdvancedConstruction_Success() { ProbingStep thirdStep = Mockito.mock(ProbingStep.class); ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addElement(thirdStep) - .addElement(secondStep) - .childBuilder() + .add(thirdStep) + .add(secondStep) .markFirstRepeated() - .addElement(firstStep) + .add(firstStep) .build(); - assertThat(sequence.next()).isEqualTo(thirdStep); - assertThat(sequence.next()).isEqualTo(secondStep); - assertThat(sequence.next()).isEqualTo(firstStep); - assertThat(sequence.next()).isEqualTo(secondStep); + assertThat(sequence.get()).isEqualTo(thirdStep); + sequence = sequence.next(); + + assertThat(sequence.get()).isEqualTo(secondStep); + sequence = sequence.next(); + + assertThat(sequence.get()).isEqualTo(firstStep); + sequence = sequence.next(); + + assertThat(sequence.get()).isEqualTo(secondStep); } @@ -130,13 +143,13 @@ public void testRunStep_Success() throws UndeterminedStateException { //Build testable sequence from mocked components. ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addElement(mockStep) - .addElement(secondStep) + .add(mockStep) + .add(secondStep) .build(); sequence.start(); - assertThat(sequence.get()).isEqualTo(secondStep); + verify(mockStep, times(1)).generateAction(testToken); } @Test @@ -155,13 +168,13 @@ public void testRunStep_FailureRunning() throws UndeterminedStateException { //Build testable sequence from mocked components. ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addElement(mockStep) - .addElement(secondStep) + .add(mockStep) + .add(secondStep) .build(); sequence.start(); - assertThat(sequence.get()).isEqualTo(secondStep); + verify(mockStep, times(1)).generateAction(testToken); } @@ -175,15 +188,15 @@ public void testRunStep_FailureGenerating() throws UndeterminedStateException { //Build testable sequence from mocked components. ProbingSequence sequence = new ProbingSequence.Builder(testToken) - .addElement(mockStep) - .addElement(secondStep) + .add(mockStep) + .add(secondStep) .build(); // When there is an error in action, generating, the next step is immediately called in the same // thread, so we expect a NullPointerException to be thrown in this thread. assertThrows(NullPointerException.class, sequence::start); - assertThat(sequence.get()).isEqualTo(secondStep); + verify(mockStep, times(1)).generateAction(testToken); } } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java index 1180f1e83bb..148558a2bee 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/tokens/WebWhoisTokenTest.java @@ -18,8 +18,7 @@ import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.messages.HttpRequestMessage; -import google.registry.util.DefaultCircularLinkedListIterator; -import java.util.Iterator; +import google.registry.util.CircularList; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -35,12 +34,12 @@ public class WebWhoisTokenTest { private static final String FIRST_TLD = "first_test"; private static final String SECOND_TLD = "second_test"; private static final String THIRD_TLD = "third_test"; - private final Iterator TEST_DOMAINS = - new DefaultCircularLinkedListIterator.Builder() - .addElements(FIRST_TLD, SECOND_TLD, THIRD_TLD) + private final CircularList testDomains = + new CircularList.Builder() + .add(FIRST_TLD, SECOND_TLD, THIRD_TLD) .build(); - public Token webToken = new WebWhoisToken(TEST_DOMAINS); + public Token webToken = new WebWhoisToken(testDomains); @Test public void testMessageModification() throws UndeterminedStateException { diff --git a/util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java b/util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java deleted file mode 100644 index 432fc659edf..00000000000 --- a/util/src/main/java/google/registry/util/AbstractCircularLinkedListIterator.java +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2019 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.util; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Iterator; - -/** - * Immutable class that support circular iteration through a group of elements of type {@param - * }. - * - * @param - Element type stored in the iterator - * - *

Is an immutable object that, when built, creates a circular pointing - * group of Entries, that allows for looped iteration. The first and last element in the closed loop - * are also stored.

- */ -public abstract class AbstractCircularLinkedListIterator implements Iterator { - - /** - * First {@link Entry} in the circular iterator. - */ - private final Entry first; - - /** - * Last {@link Entry} in the circular iterator. - */ - private final Entry last; - - /** - * Current {@link Entry} in iterator. - */ - private Entry current; - - /** - * After having established pointers between {@link Entry}s, sets first element to the first - * {@link Entry} added to {@link Builder} and sets last element to last one added to {@link - * Builder}. - */ - protected AbstractCircularLinkedListIterator(Entry first, Entry last) { - checkNotNull(last.next); - this.first = first; - this.last = last; - } - - /** - * Because this is a circular linked list iterator, there is always a next element. - */ - @Override - public boolean hasNext() { - return true; - } - - /** - * Obtains the next element by calling on the {@link Entry}'s next element. - */ - @Override - public T next() { - if (current == null) { - //If this is first call of next, return first element - - current = first; - } else { - //Otherwise return element after current element - - current = current.next; - } - - return current.data; - } - - /** - * Get method for current element in iterator. - */ - public T get() { - if (current == null) { - //if we have not started iterating, there is no current Entry, so return null - return null; - - } else { - //otherwise, retrieve the current Entry's data - return current.data; - } - } - - /** - * Returns stored first element. - */ - public T getFirst() { - return first.data; - } - - /** - * Returns stored last element. - */ - public T getLast() { - return last.data; - } - - /** - * Node class for {@link AbstractCircularLinkedListIterator} that stores value of element and - * points to next {@link Entry}. - * - * @param - Matching element type of iterator. - */ - protected static class Entry { - - /** - * Stores the {@param } instance. - */ - T data; - - /** - * Saves reference to next {@link Entry} in iterator. - */ - Entry next; - - /** - * Only needs {@param } instance for initialization. - */ - Entry(T data) { - this.data = data; - } - - /** - * Necessary for setting next {@link Entry} for subclasses outside of current package. - */ - public void setNext(Entry next) { - this.next = next; - } - } - - /** - * As {@link AbstractCircularLinkedListIterator} is an immutable class, it needs a builder for - * instantiation. - * - * @param - Matching element type of iterator - * - *

Supports adding in element at a time, adding an {@link Iterable} - * of elements, and adding an variable number of elemetns.

- * - *

Sets first element added to {@code first}, and when built, sets last added - * element to {@code last} and points it to the {@code first} element.

- */ - public abstract static class Builder, - L extends AbstractCircularLinkedListIterator> { - - /** - * Matching first entry in the circular iterator to be built. - */ - protected Entry first; - - /** - * {@link Entry} corresponding to most recent element added. - */ - protected Entry current; - - /** - * Sets current {@link Entry} to element added and points previous {@link Entry} to this one. - */ - public Builder addElement(T element) { - Entry nextEntry = new Entry<>(element); - if (current == null) { - //If this is first element added, we set it to first - first = nextEntry; - } else { - //Otherwise point previous Entry to this one - current.next = nextEntry; - } - - current = nextEntry; - return this; - } - - /** - * Simply calls {@code addElement}, for each element in {@code elements}. - */ - public Builder addElements(Iterable elements) { - elements.forEach(this::addElement); - return this; - } - - /** - * Simply calls {@code addElement}, for each element in {@code elements}. - */ - public Builder addElements(T... elements) { - for (T element : elements) { - addElement(element); - } - - return this; - } - - /** - * Converts {@link Builder} to input subclass. - * - *

Necessary for applying custom build methods when constructing - * subclasses that are inherent to the attributes of those subclasses.

- */ - public abstract B childBuilder(); - - /** - * Points last {@link Entry} to first {@link Entry}, and calls private constructor. - */ - public abstract L build(); - } -} diff --git a/util/src/main/java/google/registry/util/CircularList.java b/util/src/main/java/google/registry/util/CircularList.java new file mode 100644 index 00000000000..86f6229f439 --- /dev/null +++ b/util/src/main/java/google/registry/util/CircularList.java @@ -0,0 +1,146 @@ +// Copyright 2019 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.util; + +/** + * Class that stores value {@param }, and points in circle to other {@link CircularList} + * objects. + * + * @param - Element type stored in the {@link CircularList} + * + *

In its construction, we create a sequence of {@link CircularList} objects, each storing an + * instance of T. They each point to each other in a circular manner, such that we can perform + * circular iteration on the elements. Once finished building, we return this first {@link + * CircularList} object in the sequence.

+ */ +public class CircularList { + + /** + * T instance stored in current node of list. + */ + private final T value; + + /** + * Pointer to next node of list. + */ + private CircularList next; + + /** + * Standard constructor for {@link CircularList} that initializes its stored {@code value}. + */ + protected CircularList(T value) { + this.value = value; + } + + /** + * Standard get method to retrieve {@code value}. + */ + public T get() { + return value; + } + + /** + * Standard method to obtain {@code next} node in list. + */ + public CircularList next() { + return next; + } + + /** + * Setter method only used in builder to point one node to the next. + */ + public void setNext(CircularList next) { + this.next = next; + } + + /** + * Default Builder to create a standard instance of a {@link CircularList}. + */ + public static class Builder extends AbstractBuilder> { + + /** + * Simply calls on constructor to {@link CircularList} to create new instance. + */ + @Override + protected CircularList create(T value) { + return new CircularList<>(value); + } + + } + + /** + * As {@link CircularList} represents one component of the entire list, it requires a builder to + * create the full list. + * + * @param - Matching element type of iterator + * + *

Supports adding in element at a time, adding an {@link Iterable} + * of elements, and adding an variable number of elemetns.

+ * + *

Sets first element added to {@code first}, and when built, points last element to the + * {@code first} element.

+ */ + public abstract static class AbstractBuilder> { + + protected C first; + protected C current; + + /** + * Necessary to instantiate each {@code C} object from {@code value}. + */ + protected abstract C create(T value); + + /** + * Sets current {@code C} to element added and points previous {@code C} to this one. + */ + public AbstractBuilder add(T value) { + C c = create(value); + if (current == null) { + first = c; + } else { + current.setNext(c); + } + current = c; + return this; + } + + /** + * Simply calls {@code addElement}, for each element in {@code elements}. + */ + public AbstractBuilder add(T... values) { + for (T element : values) { + add(element); + } + return this; + } + + /** + * Simply calls {@code addElement}, for each element in {@code elements}. + */ + public AbstractBuilder add(Iterable values) { + values.forEach(this::add); + return this; + } + + /** + * Sets the next {@code C} of the list to be the first {@code C} in the list. + */ + public C build() { + current.setNext(first); + return first; + } + } + +} diff --git a/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java b/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java deleted file mode 100644 index 850773a8f08..00000000000 --- a/util/src/main/java/google/registry/util/DefaultCircularLinkedListIterator.java +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2019 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.util; - -/** - * Default implementation of {@link AbstractCircularLinkedListIterator} with generic type {@param - * } that operates only in closed circular loop. - * - * @param - Type of elements in iterator. - */ -public class DefaultCircularLinkedListIterator extends AbstractCircularLinkedListIterator { - - private DefaultCircularLinkedListIterator(Entry first, Entry last) { - super(first, last); - } - - /** - * {@link Builder} for {@link DefaultCircularLinkedListIterator}. - * - *

Doesn't do anything different than {@link AbstractCircularLinkedListIterator.Builder} but - * implementation of {@code childBuilder} and actual {@code build} methods.

- * - */ - public static class Builder extends - AbstractCircularLinkedListIterator.Builder, - DefaultCircularLinkedListIterator> { - - @Override - public Builder childBuilder() { - return this; - } - - /** - * On build, close loop by pointing last element to first. - */ - @Override - public DefaultCircularLinkedListIterator build() { - current.setNext(first); - return new DefaultCircularLinkedListIterator<>(first, current); - } - } - -} From 3d2e736fbd4f181296cbef953c2af6a01e242f55 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Fri, 9 Aug 2019 17:44:58 -0400 Subject: [PATCH 335/337] Modified ProbingSequenceTest to not expect unnecessary NullPointerException --- .../blackbox/ProbingSequenceTest.java | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index c215365e4f1..aacf068937d 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -19,7 +19,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import google.registry.monitoring.blackbox.exceptions.FailureException; @@ -40,6 +39,10 @@ * *

Then tests the execution of each step, by ensuring the methods treatment of any kind * of response from the {@link ProbingStep}s or {@link ProbingAction}s is what is expected.

+ * + *

On every test that runs the sequence, in order for the sequence to stop, we expect an + * error to be thrown on calling token.next(), as it should return null, which will create a + * {@link NullPointerException}, ending the sequence after the last step has been performed.

*/ @RunWith(JUnit4.class) public class ProbingSequenceTest { @@ -47,18 +50,19 @@ public class ProbingSequenceTest { /** * Default mock {@link ProbingAction} returned when generating an action with a mockStep. */ - private ProbingAction mockAction; + private ProbingAction mockAction = Mockito.mock(ProbingAction.class); /** * Default mock {@link ProbingStep} that will usually return a {@code mockAction} on call to * generate action. */ - private ProbingStep mockStep; + private ProbingStep mockStep = Mockito.mock(ProbingStep.class); + /** * Default mock {@link Token} that is passed into each {@link ProbingSequence} tested. */ - private Token testToken; + private Token testToken = Mockito.mock(Token.class); @Before public void setup() { @@ -67,14 +71,9 @@ public void setup() { Protocol mockProtocol = Mockito.mock(Protocol.class); doReturn(false).when(mockProtocol).persistentConnection(); - mockAction = Mockito.mock(ProbingAction.class); - //In order to avoid a NullPointerException, we must have the protocol returned that stores // persistent connection as false. - mockStep = Mockito.mock(ProbingStep.class); doReturn(mockProtocol).when(mockStep).protocol(); - - testToken = Mockito.mock(Token.class); } @Test @@ -149,7 +148,7 @@ public void testRunStep_Success() throws UndeterminedStateException { sequence.start(); - verify(mockStep, times(1)).generateAction(testToken); + verify(secondStep).generateAction(testToken); } @Test @@ -174,7 +173,7 @@ public void testRunStep_FailureRunning() throws UndeterminedStateException { sequence.start(); - verify(mockStep, times(1)).generateAction(testToken); + verify(secondStep).generateAction(testToken); } @@ -192,11 +191,25 @@ public void testRunStep_FailureGenerating() throws UndeterminedStateException { .add(secondStep) .build(); - // When there is an error in action, generating, the next step is immediately called in the same - // thread, so we expect a NullPointerException to be thrown in this thread. - assertThrows(NullPointerException.class, sequence::start); - - verify(mockStep, times(1)).generateAction(testToken); + // Since we are in main thread when the initial error is thrown, we can't expect the + // NullPointerException to just halt the flow, as it will be thrown in the main thread, not + // in ones created with future listeners. As a result, we need token.next() to throw a custom + // error which we expect. We call this CustomException. + class CustomException extends RuntimeException { + public CustomException(String msg) { + super(msg); + } + } + + //Now we tell testToken.next() to throw this exception + doThrow(new CustomException("end of sequence")).when(testToken).next(); + + //Finally verify sequence is ended by this. All of this is only used to ensure sequence is + // safely ended + assertThrows(CustomException.class, sequence::start); + + //Now we once again verify that we reach the second step despite the initial error being + // thrown and we do this by checking if the second steps generateAction function is called. + verify(secondStep).generateAction(testToken); } - } From c6361d274a6d9d36b5c4649b7029dd2729372134 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 12 Aug 2019 12:29:36 -0400 Subject: [PATCH 336/337] ProbingSequence and tests modified to reflect addition of UnrecoverableStateException and restarts on failures --- .../monitoring/blackbox/ProbingSequence.java | 75 ++++--- .../UnrecoverableStateException.java | 30 +++ .../blackbox/ProbingSequenceTest.java | 198 ++++++++++++++---- 3 files changed, 236 insertions(+), 67 deletions(-) create mode 100644 prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UnrecoverableStateException.java diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index a8d4008c1ee..4200d499e6d 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -16,6 +16,7 @@ import com.google.common.flogger.FluentLogger; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.UnrecoverableStateException; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.util.CircularList; import io.netty.bootstrap.Bootstrap; @@ -54,21 +55,21 @@ public class ProbingSequence extends CircularList { */ private boolean lastStep = false; - /** - * Standard constructor for {@link ProbingSequence} that assigns value to the node. - */ - private ProbingSequence(ProbingStep value) { - super(value); - } + private ProbingSequence first; + /** - * Constructor for first {@link ProbingSequence} in the list that assigns value and token. + * Standard constructor for {@link ProbingSequence} in the list that assigns value and token. */ private ProbingSequence(ProbingStep value, Token startToken) { - this(value); + super(value); this.startToken = startToken; } + private void setFirst(ProbingSequence first) { + this.first = first; + } + /** * Method used in {@link Builder} to mark the last step in the sequence. */ @@ -108,48 +109,60 @@ public void start() { */ private void runStep(Token token) { ProbingAction currentAction; - //attempt to generate new action. On error, move on to next step + // Attempt to generate new action. On error, move on to next step. try { currentAction = get().generateAction(token); + } catch (UnrecoverableStateException e) { + // On an UnrecoverableStateException, terminate the sequence. + logger.atSevere().withCause(e).log("Unrecoverable error in generating action."); + return; + } catch (UndeterminedStateException e) { - logger.atWarning().withCause(e).log("Error in Action Generation"); - runNextStep(token); + // On a standard UndeterminedStateException, restart the sequence at the very first step. + logger.atWarning().withCause(e).log("Error in action generation."); + + restartSequence(); return; } ChannelFuture future; try { - //call the generated action + // Call the generated action. future = currentAction.call(); } catch (Exception e) { - //On error in calling action, log error and note an error + // On error in calling action, log error and note an error. logger.atWarning().withCause(e).log("Error in Action Performed"); - //Calls next runStep - runNextStep(token); + // Restart the sequence at the very first step. + restartSequence(); return; } future.addListener(f -> { if (f.isSuccess()) { - //On a successful result, we log as a successful step, and not a success + // On a successful result, we log as a successful step, and note a success. logger.atInfo().log(String.format("Successfully completed Probing Step: %s", this)); } else { - //On a failed result, we log the failure and note either a failure or error + // On a failed result, we log the failure and note either a failure or error. logger.atSevere().withCause(f.cause()).log("Did not result in future success"); + + // If not unrecoverable, we restart the sequence. + if (!(f.cause() instanceof UnrecoverableStateException)) { + restartSequence(); + } + // Otherwise, we just terminate the full sequence. + return; } if (get().protocol().persistentConnection()) { - //If the connection is persistent, we store the channel in the token - + // If the connection is persistent, we store the channel in the token. token.setChannel(currentAction.channel()); } //Calls next runStep runNextStep(token); - }); } @@ -160,7 +173,21 @@ private void runStep(Token token) { private void runNextStep(Token token) { token = lastStep ? token.next() : token; next().runStep(token); + } + + /** + * Helper method to restart the sequence at the very first step, with a channel-less {@link + * Token}. + */ + private void restartSequence() { + // Gets next possible token to insure no replicated domains used. + Token restartToken = startToken.next(); + + // Makes sure channel from original token isn't passed down. + restartToken.setChannel(null); + // Runs the very first step with starting token. + first.runStep(restartToken); } /** @@ -192,16 +219,14 @@ public Builder markFirstRepeated() { @Override public Builder add(ProbingStep value) { super.add(value); + current.setFirst(first); + return this; } @Override protected ProbingSequence create(ProbingStep value) { - if (first == null) { - return new ProbingSequence(value, startToken); - } else { - return new ProbingSequence(value); - } + return new ProbingSequence(value, startToken); } /** diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UnrecoverableStateException.java b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UnrecoverableStateException.java new file mode 100644 index 00000000000..a9c747f9094 --- /dev/null +++ b/prober/src/main/java/google/registry/monitoring/blackbox/exceptions/UnrecoverableStateException.java @@ -0,0 +1,30 @@ +// Copyright 2019 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.monitoring.blackbox.exceptions; + +/** + * Exception thrown when error is severe enough that sequence cannot recover, and should be + * terminated as a result. + */ +public class UnrecoverableStateException extends UndeterminedStateException { + + public UnrecoverableStateException(String msg) { + super(msg); + } + + public UnrecoverableStateException(Throwable e) { + super(e); + } +} diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index aacf068937d..305fe683588 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -15,15 +15,19 @@ package google.registry.monitoring.blackbox; import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import google.registry.monitoring.blackbox.exceptions.FailureException; import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; +import google.registry.monitoring.blackbox.exceptions.UnrecoverableStateException; import google.registry.monitoring.blackbox.tokens.Token; +import io.netty.channel.Channel; +import io.netty.channel.ChannelPromise; import io.netty.channel.embedded.EmbeddedChannel; import org.junit.Before; import org.junit.Test; @@ -41,8 +45,8 @@ * of response from the {@link ProbingStep}s or {@link ProbingAction}s is what is expected.

* *

On every test that runs the sequence, in order for the sequence to stop, we expect an - * error to be thrown on calling token.next(), as it should return null, which will create a - * {@link NullPointerException}, ending the sequence after the last step has been performed.

+ * error to be thrown on calling token.next(), as it should return null, which will create a {@link + * NullPointerException}, ending the sequence after the last step has been performed.

*/ @RunWith(JUnit4.class) public class ProbingSequenceTest { @@ -62,18 +66,41 @@ public class ProbingSequenceTest { /** * Default mock {@link Token} that is passed into each {@link ProbingSequence} tested. */ - private Token testToken = Mockito.mock(Token.class); + private Token mockToken = Mockito.mock(Token.class); + + /** + * Default mock {@link Channel} returned by {@code mockAction} + */ + private Channel mockChannel = Mockito.mock(Channel.class); + + /** + * Default mock {@link Protocol} returned {@code mockStep} and occasionally, other mock {@link + * ProbingStep}s. + */ + private Protocol mockProtocol = Mockito.mock(Protocol.class); + + /** + * {@link EmbeddedChannel} used to create new {@link ChannelPromise} objects returned by mock + * {@link ProbingAction}s on their {@code call} methods. + */ + private EmbeddedChannel channel = new EmbeddedChannel(); @Before public void setup() { // To avoid a NullPointerException, we must have a protocol return persistent connection as // false. - Protocol mockProtocol = Mockito.mock(Protocol.class); - doReturn(false).when(mockProtocol).persistentConnection(); + doReturn(true).when(mockProtocol).persistentConnection(); - //In order to avoid a NullPointerException, we must have the protocol returned that stores + // In order to avoid a NullPointerException, we must have the protocol returned that stores // persistent connection as false. doReturn(mockProtocol).when(mockStep).protocol(); + + // Allows for test if channel is accurately set. + doCallRealMethod().when(mockToken).setChannel(any(Channel.class)); + doCallRealMethod().when(mockToken).channel(); + + // Allows call to mockAction to retrieve mocked channel. + doReturn(mockChannel).when(mockAction).channel(); } @Test @@ -82,7 +109,7 @@ public void testSequenceBasicConstruction_Success() { ProbingStep secondStep = Mockito.mock(ProbingStep.class); ProbingStep thirdStep = Mockito.mock(ProbingStep.class); - ProbingSequence sequence = new ProbingSequence.Builder(testToken) + ProbingSequence sequence = new ProbingSequence.Builder(mockToken) .add(firstStep) .add(secondStep) .add(thirdStep) @@ -106,7 +133,7 @@ public void testSequenceAdvancedConstruction_Success() { ProbingStep secondStep = Mockito.mock(ProbingStep.class); ProbingStep thirdStep = Mockito.mock(ProbingStep.class); - ProbingSequence sequence = new ProbingSequence.Builder(testToken) + ProbingSequence sequence = new ProbingSequence.Builder(mockToken) .add(thirdStep) .add(secondStep) .markFirstRepeated() @@ -128,9 +155,6 @@ public void testSequenceAdvancedConstruction_Success() { @Test public void testRunStep_Success() throws UndeterminedStateException { - // Create channel for the purpose of generating channel futures. - EmbeddedChannel channel = new EmbeddedChannel(); - //Always returns a succeeded future on call to mockAction. doReturn(channel.newSucceededFuture()).when(mockAction).call(); @@ -139,77 +163,167 @@ public void testRunStep_Success() throws UndeterminedStateException { //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingAction secondAction = Mockito.mock(ProbingAction.class); + + doReturn(channel.newFailedFuture(new UnrecoverableStateException(""))).when(secondAction) + .call(); + doReturn(secondAction).when(secondStep).generateAction(mockToken); //Build testable sequence from mocked components. - ProbingSequence sequence = new ProbingSequence.Builder(testToken) + ProbingSequence sequence = new ProbingSequence.Builder(mockToken) .add(mockStep) .add(secondStep) .build(); sequence.start(); - verify(secondStep).generateAction(testToken); + // We expect to have only generated actions from mockStep once, and we expect to have called + // this generated action only once, as when we move on to secondStep, it terminates the + // sequence. + verify(mockStep).generateAction(mockToken); + verify(mockAction).call(); + + // Similarly, we expect to generate actions and call the action from the secondStep once, as + // after calling it, the sequence should be terminated + verify(secondStep).generateAction(mockToken); + verify(secondAction).call(); + + //We should have modified the token's channel after the first, succeeded step. + assertThat(mockToken.channel()).isEqualTo(mockChannel); } @Test - public void testRunStep_FailureRunning() throws UndeterminedStateException { - // Create channel for the purpose of generating channel futures. - EmbeddedChannel channel = new EmbeddedChannel(); + public void testRunLoop_Success() throws UndeterminedStateException { + // Always returns a succeeded future on call to mockAction. + doReturn(channel.newSucceededFuture()).when(mockAction).call(); + + // Has mockStep always return mockAction on call to generateAction + doReturn(mockAction).when(mockStep).generateAction(mockToken); + + // Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. + ProbingStep secondStep = Mockito.mock(ProbingStep.class); + ProbingAction secondAction = Mockito.mock(ProbingAction.class); + + // Necessary for success of ProbingSequence runStep method as it calls get().protocol() + doReturn(mockProtocol).when(secondStep).protocol(); + + // We ensure that secondStep has necessary attributes to be successful step to pass on to + // mockStep once more. + doReturn(channel.newSucceededFuture()).when(secondAction).call(); + doReturn(secondAction).when(secondStep).generateAction(mockToken); + + // We get a secondToken that is returned when we are on our second loop in the sequence. This + // will inform mockStep on when to generate a different ProbingAction. + Token secondToken = Mockito.mock(Token.class); + doReturn(secondToken).when(mockToken).next(); + + // The thirdAction we use is made so that when it is called, it will halt the ProbingSequence + // by returning an UnrecoverableStateException. + ProbingAction thirdAction = Mockito.mock(ProbingAction.class); + doReturn(channel.newFailedFuture(new UnrecoverableStateException(""))).when(thirdAction).call(); + doReturn(thirdAction).when(mockStep).generateAction(secondToken); + //Build testable sequence from mocked components. + ProbingSequence sequence = new ProbingSequence.Builder(mockToken) + .add(mockStep) + .add(secondStep) + .build(); + + sequence.start(); + + // We expect to have generated actions from mockStep twice, and we expect to have called + // each generated action only once, as when we move on to mockStep the second time, it will + // terminate the sequence after calling thirdAction. + verify(mockStep, times(2)).generateAction(any(Token.class)); + verify(mockAction).call(); + verify(thirdAction).call(); + + // Similarly, we expect to generate actions and call the action from the secondStep once, as + // after calling it, we move on to mockStep again, which terminates the sequence. + verify(secondStep).generateAction(any(Token.class)); + verify(secondAction).call(); + + //We should have modified the token's channel after the first, succeeded step. + assertThat(mockToken.channel()).isEqualTo(mockChannel); + } + + @Test + public void testRunStep_FailureRunning() throws UndeterminedStateException { // Returns a failed future when calling the generated mock action. doReturn(channel.newFailedFuture(new FailureException(""))).when(mockAction).call(); // Returns mock action on call to generate action for ProbingStep. - doReturn(mockAction).when(mockStep).generateAction(any(Token.class)); + doReturn(mockAction).when(mockStep).generateAction(mockToken); //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. ProbingStep secondStep = Mockito.mock(ProbingStep.class); + // We create a second token that when used to generate an action throws an + // UnrecoverableStateException to terminate the sequence + Token secondToken = Mockito.mock(Token.class); + doReturn(secondToken).when(mockToken).next(); + doThrow(new UnrecoverableStateException("")).when(mockStep).generateAction(secondToken); + //Build testable sequence from mocked components. - ProbingSequence sequence = new ProbingSequence.Builder(testToken) + ProbingSequence sequence = new ProbingSequence.Builder(mockToken) .add(mockStep) .add(secondStep) .build(); sequence.start(); - verify(secondStep).generateAction(testToken); + //We expect that we have generated actions twice. First, when we generate a real action, and + // second when we throw an UnrecoverableStateException. + verify(mockStep, times(2)).generateAction(any(Token.class)); + + // We only expect to have called this action once, as we only get it from one generateAction + // call. + verify(mockAction).call(); + + // We should never reach the step where we modify the channel, as it should have failed by then + assertThat(mockToken.channel()).isNull(); + + // We should never reach the second step, since we fail on the first step, then terminate on + // the first step after retrying. + verify(secondStep, times(0)).generateAction(any(Token.class)); } @Test public void testRunStep_FailureGenerating() throws UndeterminedStateException { // Create a mock first step that returns the dummy action when called to generate an action. - doThrow(UndeterminedStateException.class).when(mockStep).generateAction(any(Token.class)); + doThrow(UndeterminedStateException.class).when(mockStep).generateAction(mockToken); //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. ProbingStep secondStep = Mockito.mock(ProbingStep.class); + // We create a second token that when used to generate an action throws an + // UnrecoverableStateException to terminate the sequence + Token secondToken = Mockito.mock(Token.class); + doReturn(secondToken).when(mockToken).next(); + doThrow(new UnrecoverableStateException("")).when(mockStep).generateAction(secondToken); + //Build testable sequence from mocked components. - ProbingSequence sequence = new ProbingSequence.Builder(testToken) + ProbingSequence sequence = new ProbingSequence.Builder(mockToken) .add(mockStep) .add(secondStep) .build(); - // Since we are in main thread when the initial error is thrown, we can't expect the - // NullPointerException to just halt the flow, as it will be thrown in the main thread, not - // in ones created with future listeners. As a result, we need token.next() to throw a custom - // error which we expect. We call this CustomException. - class CustomException extends RuntimeException { - public CustomException(String msg) { - super(msg); - } - } - - //Now we tell testToken.next() to throw this exception - doThrow(new CustomException("end of sequence")).when(testToken).next(); - - //Finally verify sequence is ended by this. All of this is only used to ensure sequence is - // safely ended - assertThrows(CustomException.class, sequence::start); - - //Now we once again verify that we reach the second step despite the initial error being - // thrown and we do this by checking if the second steps generateAction function is called. - verify(secondStep).generateAction(testToken); + sequence.start(); + + //We expect that we have generated actions twice. First, when we throw a generic + // UndeterminedException, and second when we throw an UnrecoverableStateException. + verify(mockStep, times(2)).generateAction(any(Token.class)); + + // We expect to have never called this action, as we fail each time whenever generating actions. + verify(mockAction, times(0)).call(); + + // We should never reach the step where we modify the channel, as it should have failed by then + assertThat(mockToken.channel()).isNull(); + assertThat(secondToken.channel()).isNull(); + + // We should never reach the second step, since we fail on the first step, then terminate on + // the first step after retrying. + verify(secondStep, times(0)).generateAction(any(Token.class)); } } From 1309bcd1a35b59e4529816bb833f6315931b2a04 Mon Sep 17 00:00:00 2001 From: Aman Sanger Date: Mon, 12 Aug 2019 17:22:01 -0400 Subject: [PATCH 337/337] Modified ProbingSequence and its tests to reflect action generation and calling being put in the same try catch block --- .../monitoring/blackbox/ProbingSequence.java | 48 ++++---- .../blackbox/ProbingSequenceTest.java | 103 ++++++++---------- 2 files changed, 69 insertions(+), 82 deletions(-) diff --git a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java index 4200d499e6d..c9757c00673 100644 --- a/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java +++ b/prober/src/main/java/google/registry/monitoring/blackbox/ProbingSequence.java @@ -15,7 +15,6 @@ package google.registry.monitoring.blackbox; import com.google.common.flogger.FluentLogger; -import google.registry.monitoring.blackbox.exceptions.UndeterminedStateException; import google.registry.monitoring.blackbox.exceptions.UnrecoverableStateException; import google.registry.monitoring.blackbox.tokens.Token; import google.registry.util.CircularList; @@ -27,10 +26,13 @@ /** * Represents Sequence of {@link ProbingStep}s that the Prober performs in order. * - *

Inherits from {@link CircularList}

, with element type of - * {@link ProbingStep} as the manner in which the sequence is carried out is analogous to the {@link - * CircularList} - * + *

Inherits from {@link CircularList}, with element type of + * {@link ProbingStep} as the manner in which the sequence is carried out is similar to the {@link + * CircularList}. However, the {@link Builder} of {@link ProbingSequence} override + * {@link CircularList.AbstractBuilder} allowing for more customized flows, that are looped, but + * not necessarily entirely circular. + * Example: first -> second -> third -> fourth -> second -> third -> fourth -> second -> ... + *

* *

Created with {@link Builder} where we specify {@link EventLoopGroup}, {@link AbstractChannel} * class type, then sequentially add in the {@link ProbingStep.Builder}s in order and mark which one @@ -55,6 +57,9 @@ public class ProbingSequence extends CircularList { */ private boolean lastStep = false; + /** + * {@link ProbingSequence} object that represents first step in the sequence. + */ private ProbingSequence first; @@ -66,10 +71,6 @@ private ProbingSequence(ProbingStep value, Token startToken) { this.startToken = startToken; } - private void setFirst(ProbingSequence first) { - this.first = first; - } - /** * Method used in {@link Builder} to mark the last step in the sequence. */ @@ -109,29 +110,24 @@ public void start() { */ private void runStep(Token token) { ProbingAction currentAction; - // Attempt to generate new action. On error, move on to next step. + ChannelFuture future; + try { + // Attempt to generate new action. On error, move on to next step. currentAction = get().generateAction(token); - } catch (UnrecoverableStateException e) { - // On an UnrecoverableStateException, terminate the sequence. - logger.atSevere().withCause(e).log("Unrecoverable error in generating action."); - return; - } catch (UndeterminedStateException e) { - // On a standard UndeterminedStateException, restart the sequence at the very first step. - logger.atWarning().withCause(e).log("Error in action generation."); + // Call the generated action. + future = currentAction.call(); - restartSequence(); + } catch (UnrecoverableStateException e) { + // On an UnrecoverableStateException, terminate the sequence. + logger.atSevere().withCause(e).log( + "Unrecoverable error in generating or calling action."); return; - } - ChannelFuture future; - try { - // Call the generated action. - future = currentAction.call(); } catch (Exception e) { - // On error in calling action, log error and note an error. - logger.atWarning().withCause(e).log("Error in Action Performed"); + // On any other type of error, restart the sequence at the very first step. + logger.atWarning().withCause(e).log("Error in generating or calling action."); // Restart the sequence at the very first step. restartSequence(); @@ -219,7 +215,7 @@ public Builder markFirstRepeated() { @Override public Builder add(ProbingStep value) { super.add(value); - current.setFirst(first); + current.first = first; return this; } diff --git a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java index 305fe683588..97ea630f939 100644 --- a/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java +++ b/prober/src/test/java/google/registry/monitoring/blackbox/ProbingSequenceTest.java @@ -44,9 +44,9 @@ *

Then tests the execution of each step, by ensuring the methods treatment of any kind * of response from the {@link ProbingStep}s or {@link ProbingAction}s is what is expected.

* - *

On every test that runs the sequence, in order for the sequence to stop, we expect an - * error to be thrown on calling token.next(), as it should return null, which will create a {@link - * NullPointerException}, ending the sequence after the last step has been performed.

+ *

On every test that runs the sequence, in order for the sequence to stop, we throw an + * {@link UnrecoverableStateException}, using mocks of the steps or actions, as the sequences + * are run using the main thread (with {@link EmbeddedChannel}).

*/ @RunWith(JUnit4.class) public class ProbingSequenceTest { @@ -68,11 +68,6 @@ public class ProbingSequenceTest { */ private Token mockToken = Mockito.mock(Token.class); - /** - * Default mock {@link Channel} returned by {@code mockAction} - */ - private Channel mockChannel = Mockito.mock(Channel.class); - /** * Default mock {@link Protocol} returned {@code mockStep} and occasionally, other mock {@link * ProbingStep}s. @@ -100,7 +95,7 @@ public void setup() { doCallRealMethod().when(mockToken).channel(); // Allows call to mockAction to retrieve mocked channel. - doReturn(mockChannel).when(mockAction).channel(); + doReturn(channel).when(mockAction).channel(); } @Test @@ -180,16 +175,18 @@ public void testRunStep_Success() throws UndeterminedStateException { // We expect to have only generated actions from mockStep once, and we expect to have called // this generated action only once, as when we move on to secondStep, it terminates the // sequence. + verify(mockStep).generateAction(any(Token.class)); verify(mockStep).generateAction(mockToken); verify(mockAction).call(); // Similarly, we expect to generate actions and call the action from the secondStep once, as // after calling it, the sequence should be terminated + verify(secondStep).generateAction(any(Token.class)); verify(secondStep).generateAction(mockToken); verify(secondAction).call(); //We should have modified the token's channel after the first, succeeded step. - assertThat(mockToken.channel()).isEqualTo(mockChannel); + assertThat(mockToken.channel()).isEqualTo(channel); } @Test @@ -231,30 +228,33 @@ public void testRunLoop_Success() throws UndeterminedStateException { sequence.start(); - // We expect to have generated actions from mockStep twice, and we expect to have called - // each generated action only once, as when we move on to mockStep the second time, it will - // terminate the sequence after calling thirdAction. + // We expect to have generated actions from mockStep twice (once for mockToken and once for + // secondToken), and we expectto have called each generated action only once, as when we move + // on to mockStep the second time, it will terminate the sequence after calling thirdAction. verify(mockStep, times(2)).generateAction(any(Token.class)); + verify(mockStep).generateAction(mockToken); + verify(mockStep).generateAction(secondToken); verify(mockAction).call(); verify(thirdAction).call(); // Similarly, we expect to generate actions and call the action from the secondStep once, as // after calling it, we move on to mockStep again, which terminates the sequence. verify(secondStep).generateAction(any(Token.class)); + verify(secondStep).generateAction(mockToken); verify(secondAction).call(); //We should have modified the token's channel after the first, succeeded step. - assertThat(mockToken.channel()).isEqualTo(mockChannel); + assertThat(mockToken.channel()).isEqualTo(channel); } - @Test - public void testRunStep_FailureRunning() throws UndeterminedStateException { - // Returns a failed future when calling the generated mock action. - doReturn(channel.newFailedFuture(new FailureException(""))).when(mockAction).call(); - - // Returns mock action on call to generate action for ProbingStep. - doReturn(mockAction).when(mockStep).generateAction(mockToken); - + /** + * Test for when we expect Failure within try catch block of generating and calling a + * {@link ProbingAction}. + * + * @throws UndeterminedStateException - necessary for having mock return anything on a call to + * {@code generateAction}. + */ + private void testActionFailure() throws UndeterminedStateException { //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. ProbingStep secondStep = Mockito.mock(ProbingStep.class); @@ -272,58 +272,49 @@ public void testRunStep_FailureRunning() throws UndeterminedStateException { sequence.start(); - //We expect that we have generated actions twice. First, when we generate a real action, and - // second when we throw an UnrecoverableStateException. + // We expect that we have generated actions twice. First, when we actually test generateAction + // with an actual call using mockToken, and second when we throw an + // UnrecoverableStateException with secondToken. verify(mockStep, times(2)).generateAction(any(Token.class)); - - // We only expect to have called this action once, as we only get it from one generateAction - // call. - verify(mockAction).call(); + verify(mockStep).generateAction(mockToken); + verify(mockStep).generateAction(secondToken); // We should never reach the step where we modify the channel, as it should have failed by then assertThat(mockToken.channel()).isNull(); + assertThat(secondToken.channel()).isNull(); // We should never reach the second step, since we fail on the first step, then terminate on // the first step after retrying. verify(secondStep, times(0)).generateAction(any(Token.class)); } - @Test - public void testRunStep_FailureGenerating() throws UndeterminedStateException { - // Create a mock first step that returns the dummy action when called to generate an action. - doThrow(UndeterminedStateException.class).when(mockStep).generateAction(mockToken); + public void testRunStep_FailureRunning() throws UndeterminedStateException { + // Returns a failed future when calling the generated mock action. + doReturn(channel.newFailedFuture(new FailureException(""))).when(mockAction).call(); - //Dummy step that server purpose of placeholder to test ability of ProbingSequence to move on. - ProbingStep secondStep = Mockito.mock(ProbingStep.class); + // Returns mock action on call to generate action for ProbingStep. + doReturn(mockAction).when(mockStep).generateAction(mockToken); - // We create a second token that when used to generate an action throws an - // UnrecoverableStateException to terminate the sequence - Token secondToken = Mockito.mock(Token.class); - doReturn(secondToken).when(mockToken).next(); - doThrow(new UnrecoverableStateException("")).when(mockStep).generateAction(secondToken); + //Tests generic behavior we expect when we fail in generating or calling an action. + testActionFailure(); - //Build testable sequence from mocked components. - ProbingSequence sequence = new ProbingSequence.Builder(mockToken) - .add(mockStep) - .add(secondStep) - .build(); + // We only expect to have called this action once, as we only get it from one generateAction + // call. + verify(mockAction).call(); - sequence.start(); - //We expect that we have generated actions twice. First, when we throw a generic - // UndeterminedException, and second when we throw an UnrecoverableStateException. - verify(mockStep, times(2)).generateAction(any(Token.class)); + } - // We expect to have never called this action, as we fail each time whenever generating actions. - verify(mockAction, times(0)).call(); - // We should never reach the step where we modify the channel, as it should have failed by then - assertThat(mockToken.channel()).isNull(); - assertThat(secondToken.channel()).isNull(); + @Test + public void testRunStep_FailureGenerating() throws UndeterminedStateException { + // Create a mock first step that returns the dummy action when called to generate an action. + doThrow(UndeterminedStateException.class).when(mockStep).generateAction(mockToken); - // We should never reach the second step, since we fail on the first step, then terminate on - // the first step after retrying. - verify(secondStep, times(0)).generateAction(any(Token.class)); + testActionFailure(); + + // We expect to have never called this action, as we fail each time whenever generating actions. + verify(mockAction, times(0)).call(); } }